Ассамблея 8086 | Сумма массива, печать многозначных чисел

Я написал довольно простой код в asm x8086, и я столкнулся с ошибкой. Если бы кто-нибудь мог помочь мне с кратким объяснением, я бы очень признателен.

IDEAL MODEL small STACK 100h DATASEG ; -------------------------- array db 10h, 04h, 04h, 04h, 04h, 04h, 04h, 04h, 04h, 04h sum db 0 ; -------------------------- CODESEG start: mov ax, @data mov ds, ax ; -------------------------- xor cx, cx mov al, 0 mov bx, offset array StartLoop: cmp cx, 10 jge EndLoop add al, [bx] add [sum],al inc cx inc bx jmp StartLoop EndLoop: mov ah, 09h int 21h ; -------------------------- exit: mov ax, 4c00h int 21h END start 

С поправкой на add которое нужно заменить mov как указано в вашем комментарии ( обратите внимание, что строка: add al, [bx] на самом деле mov al, [bx] ) есть только вызов функции на ярлыке EndLoop , это неправильно!

Вы хотите отобразить сумму и используете функцию печати DOS. Эта функция 09h ожидает указателя в DS: DX, который вы не предоставляете!
Даже если вы это сделали, вам все равно придется преобразовать номер суммы в его текстовое представление.

Быстрое решение здесь заключалось бы в том, чтобы конкретизировать себя и просто отобразить результат в виде одного символа ASCII. Жестко закодированная сумма равна 52 и поэтому является отображаемым символом:

 EndLoop: mov dl, [sum] mov ah, 02h ;Single character output int 21h ; -------------------------- exit: mov ax, 4c00h int 21h 

Еще один шаг, и мы можем отобразить «52»:

 mov al,[sum] mov ah,0 mov dl,10 div dl ---> AL=5 AH=2 add ax,3030h ---> AL="5" AH="2" mov dh,ah ;preserve AH mov dl,al mov ah,02h int 21h mov dl,dh ;restore int 21h 

Я вообще не вижу никакой ошибки, код будет суммировать массив, отображать некоторые случайные sh * t и выходить.

Вероятно, вы хотите отобразить результат суммы?

int 21h, ah=9 отобразит строку '$' terminated из памяти, на которую указывает dx .

Итак, вам нужно две вещи, конвертировать число в [sum] в строку, завершенную '$' в конце, а затем установить dx в преобразованную строку перед этим int 21h .

Вы можете попробовать number2string процедуру number2string здесь: https://stackoverflow.com/a/29826819/4271923

Я лично изменил бы его, чтобы принять адрес целевого буфера в si качестве другого аргумента вызова (т. mov si,offset str Просто удалите mov si,offset str из тела процедуры). Как это:

 PROC number2string ; arguments: ; ax = unsigned number to convert ; si = pointer to string buffer (must have 6+ bytes) ; modifies: ax, bx, cx, dx, si mov bx, 10 ; radix 10 (decimal number formatting) xor cx, cx ; counter of extracted digits set to zero number2string_divide_by_radix: ; calculate single digit xor dx, dx ; dx = 0 (dx:ax = 32b number to divide) div bx ; divide dx:ax by radix, remainder will be in dx ; store the remainder in stack push dx inc cx ; loop till number is zero test ax, ax jnz number2string_divide_by_radix ; now convert stored digits in stack into string number2string_write_string: pop dx add dl, '0' ; convert 0-9 value into '0'-'9' ASCII character encoding ; store character at end of string mov [si], dl inc si ; loop till all digits are written dec cx jnz number2string_write_string ; store '$' terminator at end mov BYTE PTR [si],'$' ret ENDP 

Затем, чтобы вызвать это на вашем EndLoop вам нужно добавить номер сегмента numberStr DB 8 DUP (0) чтобы иметь буфер памяти, выделенный для строки и добавить в код:

  ; load sum as 16b unsigned value into ax xor ax,ax ; ax = 0 mov al,[sum] ; ax = sum (16b zero extended) ; convert it to string mov si,OFFSET numberStr call number2string ; display the '$' terminated string mov dx,OFFSET numberStr mov ah,9 int 21h ; ... exit ... 
Давайте будем гением компьютера.