Я сейчас пишу ассемблерную программу, которая работает в реальном режиме.
Я компилирую его с помощью NASM.
Моя проблема заключается в том, что если я пытаюсь вызвать одну функцию из другой, она выполняется только в том случае, если я вычту очень высокое значение из esp (70) или если у меня нет выдвинутых аргументов.
Я думаю, что что-то не так с тем, как я вызываю функции, но я не могу понять, что.
Код комлета:
; boot.asm
[ORG 0x7c00] ;set base addresse
;mov ax, 0x7c0
xor ax, ax ; set zero
mov ds, ax ; set data pointer
mov ss, ax ; set stack start ptr
mov sp, 0x2000
add sp, ax
call main
hang:
jmp hang
main:
push ebp
mov ebp, esp
push 0x13
call setVideoMode_mode
add esp, 2
push 2
push 320*200
call clearScreen_char_n
add esp, 4
push 100
call drawVerticalLine
add esp, 2
nop
mov esp, ebp
pop ebp
ret
setVideoMode_mode:
push ebp
mov ebp, esp
mov ah, 0x00 ;change mode command
mov al, [ebp+6] ;video mode
int 0x10 ;execute command
mov esp, ebp
pop ebp
ret
putPixel_pos_char:
push ebp
mov ebp, esp
sub esp, 16 ; 3 local vars
mov eax, DWORD [ebp+8] ;POS
mov WORD [ebp-12], ax
mov eax, DWORD [ebp+6] ;CHAR
mov WORD [ebp-8], ax
mov DWORD [ebp-4], 0xA0000 ;STD VIDEO POINTER
mov eax, [ebp-12]
add eax, DWORD [ebp-4]
movzx edx, WORD [ebp-8]
mov BYTE [eax], dl
nop
; leave
mov esp, ebp
pop ebp
ret
;----------------------------
Проблемная функция:
drawVerticalLine: ;doing debugging stuf at the moment
push ebp
mov ebp, esp
sub esp, 16 ;the function call only works with 70 or higher / no arguments for this function
mov eax, DWORD [ebp+6]
mov WORD [ebp-4], ax
push 4
push 320*200
call clearScreen_char_n ;not working (should make the screen red)
add esp, 4
nop
mov esp, ebp
push ebp
ret
clearScreen_char_n:
push ebp
mov ebp, esp
sub esp, 32
mov eax, DWORD [ebp+8]
mov WORD [ebp-12], ax ; CHAR
mov eax, DWORD [ebp+6]
mov WORD [ebp-8], ax ; N
mov DWORD [ebp-4], 0 ; COUNTER
jmp .LoopCompare
.LoopBody:
push WORD [ebp-4] ;COUNTER
push WORD [ebp-12] ;CHAR
call putPixel_pos_char
add esp, 4
inc DWORD[ebp-4] ;COUNTER ++
.LoopCompare:
mov ax, WORD [ebp-8] ;N
cmp ax, WORD [ebp-4] ;COUNTER
jne .LoopBody ;NOT EQUAL
nop
mov esp, ebp
pop ebp
ret
times 510-($-$$) db 0
db 0x55 ;mark bootsector
db 0xAA
Спасибо за вашу помощь.
EDIT:
Я только заметил еще более странную вещь:
Если я отлаживаю с помощью gdb и logg sp после каждой инструкции (точки останова + x / x $ sp) (кроме цикла), это волшебным образом работает так, как должно.
Если я запускаю с GDB без каких-либо точек останова, он снова не работает.