Сборка 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
2 ответа
С поправкой на 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
будет отображать '$'
завершенная строка из памяти, на которую указывает dx
,
Таким образом, вам нужно две вещи, преобразовать число в [sum]
строка завершается'$'
в конце, а затем установить dx
перед преобразованной строкой int 21h
,
Вы можете попробовать извлечь number2string
процедура отсюда: /questions/11755424/sborka-kak-sdelat-summu-mezhdu-dvumya-chislami-interval/11755430#11755430
Я бы лично изменил его на адрес целевого буфера в si
в качестве другого аргумента вызова (т.е. просто удалите 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 ...