Почему эта функция ASM не печатает должным образом?
Я пытаюсь написать небольшую функцию для печати строки с нулевым символом в конце или строки фиксированной длины в определенной ячейке памяти. Вот мой код:
vbrstart:
xor eax, eax
mov sp, 0x7a00
mov bp, 0x6000
mov ss, ax
mov ds, ax
mov es, ax
xor ebx, ebx
xor ecx, ecx
push strict dword initializing
push strict word 0x0000
call printmsg
jmp end
;push strict dword memloc
;push strict word length
;call printmsg
printmsg:
pop strict dword [store_ret]
mov [store_cx], cx
mov [store_esi], esi
pop cx
pop esi
push eax
push ebx
mov ah, 0x0E
mov bx, 0x0007
cmp cx, 0x0000
je printnullterm
printgivenlen:
lodsb
cmp cx, 0x0000
je printdone
int 10h
dec cx
jmp printgivenlen
printnullterm:
lodsb
cmp al, 0x00
je printdone
int 10h
jmp printnullterm
printdone:
pop ebx
pop eax
mov esi, [store_esi]
mov cx, [store_cx]
push strict dword [store_ret]
ret
printdata:
store_cx dw 0
store_esi dd 0
store_ret dd 0
end:
hlt
jmp end
initializing db 10,13,'Initializing...',0
При тестировании он печатается неопределенно долго и не останавливается на нулевом байте. Где я ошибся?
2 ответа
Я вижу 2 проблемы с вашим кодом:
Вы написали загрузчик. Такая программа работает в режиме 16-битного реального адреса. Это подразумевает, что адрес возврата от
call
будет словом, а не словом, как ожидает ваш код.printmsg: pop word [store_ret]
Вы устанавливаете стек в рискованной манере. Вам нужно сначала изменить регистр SS и сразу после этого регистр SP.
xor ax, ax mov ss, ax <<< Keep these together mov sp, 0x7a00 <<< and in this order!
Поскольку это 16-битный код, нет необходимости push
/ pop
адрес как меч.
push word initializing
...
pop si
Ваш стек неправильно выровнен со всеми толчками и трещотками. Проверьте параметры передачи и их использование в рутине. Для начала вот подсказка:
vbrstart:
xor eax, eax
mov sp, 0x7a00
mov bp, 0x6000
mov ss, ax
mov ds, ax
mov es, ax
xor ebx, ebx
xor ecx, ecx
push strict dword initializing
push strict word 0x0000
call printmsg ; near call, only 16 bits ret addr stored
jmp end
;push strict dword memloc
;push strict word length
;call printmsg
printmsg:
pop strict dword [store_ret] ; pop dword (ret address + 16 bits- 1st argument)
mov [store_cx], cx ; store_cx = 0
mov [store_esi], esi ; store_esi = ??
pop cx ; cx = initializing
. . .