nasm 无法在函数中调用函数
nasm can't call function in function
所以我最近又搬到 nasm 并尝试构建一些基本的东西(putc 和 puts)。
Putc
工作正常但问题是在我调用 puts
中的 putc
之后,putc
中的 ret
没有 return 到 puts
推入堆栈的 ip
,因此在 puts
中不再执行更多指令(在 gdb 中调试了该部分)。
msg db "Welcome!", 0ah, 0dh, 0h
putc:
push ebp
mov esp, ebp
mov ah, 0ah
; al is set before
mov bh, 0
mov bl, 0
mov cx, 1
int 10h
ret
puts:
push ebp
mov esp, ebp
mov ebx, msg
dec ebx
puts_l:
inc ebx
mov al, [ebx]
call putc
cmp al, 0h
jne puts_l
ret
这显然不是最好的,但我想我在某处有误解。我可以想象寄存器会被 putc 覆盖,但这并不能说明为什么 putc 中的 ret
不会 return 到 puts
我还应该提到我正在使用 x86。
当你这样做时
push ebp
mov esp, ebp
esp
不再指向被压入的ebp
和return地址,这是无法解决的问题通过使用 LEAVE in the function epilogue. BTW LEAVE
should be paired with ENTER.
如果您确实需要堆栈帧(例如定义一个本地内存变量),框架可能如下所示:
Function:
PUSH EBP
MOV EBP,ESP
SUB ESP,4 ; The local variable is now addressable as [ESP] alias [EBP-4].
; Here is the Function body which can use local variable(s).
MOV ESP,EBP ; Discard local variable, ESP will point to the saved EBP.
POP EBP ; Restore EBP which might be used as parent's frame pointer.
RET
由于您的程序不使用局部变量,因此可能
mov esi, msg ; Address of the ASCIIZ string.
call puts
jmp $ ; Program ends here.
puts: ; Function which displays ASCIIZ string at ESI.
lodsb ; Load AL from [DS:ESI], increment ESI.
cmp al, 0h
je puts_2
call putc ; Display a nonzero character in AL.
jmp puts
puts_2: ret
putc: ; Function which displays a character in AL.
mov ah, 0ah ; WRITE CHARACTER.
mov bh, 0 ; Videopage 0.
mov bl, 0 ; Colour in graphic mode.
mov cx, 1 ; Number of times to write character
int 10h ; Invoke BIOS videofunction.
ret
msg db "Welcome!", 0ah, 0dh, 0h ; The displayed ASCIIZ string.
所以我最近又搬到 nasm 并尝试构建一些基本的东西(putc 和 puts)。
Putc
工作正常但问题是在我调用 puts
中的 putc
之后,putc
中的 ret
没有 return 到 puts
推入堆栈的 ip
,因此在 puts
中不再执行更多指令(在 gdb 中调试了该部分)。
msg db "Welcome!", 0ah, 0dh, 0h
putc:
push ebp
mov esp, ebp
mov ah, 0ah
; al is set before
mov bh, 0
mov bl, 0
mov cx, 1
int 10h
ret
puts:
push ebp
mov esp, ebp
mov ebx, msg
dec ebx
puts_l:
inc ebx
mov al, [ebx]
call putc
cmp al, 0h
jne puts_l
ret
这显然不是最好的,但我想我在某处有误解。我可以想象寄存器会被 putc 覆盖,但这并不能说明为什么 putc 中的 ret
不会 return 到 puts
我还应该提到我正在使用 x86。
当你这样做时
push ebp
mov esp, ebp
esp
不再指向被压入的ebp
和return地址,这是无法解决的问题通过使用 LEAVE in the function epilogue. BTW LEAVE
should be paired with ENTER.
如果您确实需要堆栈帧(例如定义一个本地内存变量),框架可能如下所示:
Function:
PUSH EBP
MOV EBP,ESP
SUB ESP,4 ; The local variable is now addressable as [ESP] alias [EBP-4].
; Here is the Function body which can use local variable(s).
MOV ESP,EBP ; Discard local variable, ESP will point to the saved EBP.
POP EBP ; Restore EBP which might be used as parent's frame pointer.
RET
由于您的程序不使用局部变量,因此可能
mov esi, msg ; Address of the ASCIIZ string.
call puts
jmp $ ; Program ends here.
puts: ; Function which displays ASCIIZ string at ESI.
lodsb ; Load AL from [DS:ESI], increment ESI.
cmp al, 0h
je puts_2
call putc ; Display a nonzero character in AL.
jmp puts
puts_2: ret
putc: ; Function which displays a character in AL.
mov ah, 0ah ; WRITE CHARACTER.
mov bh, 0 ; Videopage 0.
mov bl, 0 ; Colour in graphic mode.
mov cx, 1 ; Number of times to write character
int 10h ; Invoke BIOS videofunction.
ret
msg db "Welcome!", 0ah, 0dh, 0h ; The displayed ASCIIZ string.