Edit: переписал и добавил текст, добавил код (работает в MASM 6.11):
В x86 assembbly необходимо указать размер операнда памяти для инструкций, в которых были бы неоднозначность иначе. Вы должны сообщить ассемблеру размер операнда с byte ptr
, word ptr
и т. Д. По этой причине inc byte ptr ds:[count]
нуждается в byte ptr
. inc word ptr ds:[count
- другая инструкция.
mov dl,ds:[count]
не нужен byte ptr
, потому что dl
является 8-разрядным регистром, и поэтому размер операнда памяти всегда один и тот же, байт (8 бит).
Для печати символов вам необходимо сначала преобразовать число в строку (или один символ для чисел меньше 10). В противном случае вы печатаете управление символом ETX (см ASCII table), который имеет ASCII-код 3. Для чисел меньше 10, печать в десятичном тривиальна, просто добавьте «0» (30h
), как это:
mov dl,ds:[count]
add dl,'0' ; add dl,30h
Печати в decimal в x86-сборке задается довольно часто, см., например, Is this code correct (Number plus number, then print the result), чтобы получить эту идею.
Редактировать: В файлах EXE также должен быть сегмент стека.
Файлы DOS EXE должны иметь сегмент стека. Сборка с MASM 6.11 не дает никаких предупреждений или ошибок, в основном с dosexe.asm
(замените doctxe.asm на имя файла кода сборки).
Но связь с ML (ml dosexe.obj
) дает следующее предупреждение:
LINK : warning L4021: no stack segment
Таким образом, сегмент стека должен быть добавлен, добавьте следующие строки в верхней части источника.
.model small
.stack 4096
Была также проблема с определением сегмента данных, я также исправил это.
Весь фиксированный код сборки может быть что-то вроде этого (работает в MASM 6.11):
.model small
.stack 4096
.data
count db 0
.code
start:
mov ax,seg count
mov ds,ax
inc byte ptr ds:[count]
inc byte ptr ds:[count]
inc byte ptr ds:[count]
; this code does the printing in decimal without needing to reverse
; the string, by dividing the divisor. 100/10 = 10
mov bl,100 ; original divisor.
mov al,ds:[count]
print_loop:
xor ah,ah ; clear top 8 bits of the dividend (in ax).
div bl ; divide ax by bl. quotient in al, remainder in ah.
mov dl,al ; the value to be printed with ah = 2, int 21h
mov al,ah ; remainder gets divided in the next loop.
test dl,dl ; check if number is zero
jz not_print ; don't print leading zeros.
add dl,'0' ; convert to ASCII numeric characters range.
; '0' = 0x30 = 48
push ax
mov ah,2
int 21h ; print the value, according to Ralf Brown's
pop ax ; interrupt list returns al.
not_print:
push ax
mov al,bl
xor ah,ah
mov bl,10 ; divide the divisor by 10.
div bl
mov bl,al ; the new divisor.
pop ax
test bl,bl
jnz print_loop
mov ah,4ch
int 21h
end start
я не знаю об этом собрании, но вы уверены, что не увеличивает указатель вместо значения в регистрах? это сообщение об ошибке кажется повреждением кучи. – Jack