我正在尝试解决这个问题:
创建一个PROC过程,该过程将一个参数作为按值传递,并根据作为参数传递的数字打印“X”的数字。 在打印之前,请确保参数为正数,程序结束时需要将已使用的寄存器更改回其初始值。
如果该过程的输入为 5,则控制台上的输出应为:
XXXXX
这是我的代码:
var db 5 ;In the dataseg
push [var] ;in the codeseg
proc example
pop cx
cmp cx,0
ja print
print:
mov dl, 'X'
mov ah, 2h
int 21h
loop print
ret
endp example
这段代码会按预期工作吗?如果没有,为什么?如何解决?
最佳答案
作为 Peter 答案的附录,您可以使用 MASM/TASM 生成序言和尾声代码来为您设置BP,并允许您通过标签访问过程/函数参数。关于 MASM 和 TASM 使用的 PROC 子例程的相当好的教程可以在 here 找到。
我还将 var
更改为 WORD 而不是 BYTE。生成的代码如下所示:
.MODEL SMALL
.STACK 100H
.DATA
var dw 5 ; Change to 16-bit WORD
.CODE
example proc C ; C Calling convention - parameters on stack right to left
ARG num:WORD ; We take one argument called `num` that is a word
mov cx, num ; Move the 16-bit value in `num` to CX counter
; same as: mov cx, [bp+4]
; [bp+0] is saved copy of BP put on stack by MASM's prologue
; [bp+2] return address placed on stack by CALL
cmp cx, 0
jle negative ; If we are less than or equal to 0, exit procedure
mov dl, 'X'
mov ah, 2h ; ah and dl not destroyed by int 21h/ah=2 so set them once
; before loop
print:
int 21h ; Print an 'X'
loop print ; Continue until loop is 0
negative:
ret
endp example
main proc
mov ax, @data ; initialize DS
mov ds, ax
push [var] ; Push 2-byte value at `var` (pushing by value)
call example
add sp, 2 ; Remove parameter from stack
; Not necessary since we use int 21h to exit right after
mov ah, 4ch ; return control to DOS
int 21h
main endp
end main ; Entry point = label main
上面的代码将为过程示例
生成这些指令:
example proc
push bp ; Save BP on stack \
mov bp, sp ; Set BP to SP / Function prologue
; [bp+0] is saved copy of BP put on stack by prologue
; [bp+2] return address placed on stack by CALL
; [bp+4] first parameter (NUM)
mov cx, [bp+4] ; Move the value at BP+4 (NUM) to CX counter
cmp cx, 0
jle negative ; If we are less than or equal to 0, exit procedure
mov dl, 'X'
mov ah, 2h ; ah and dl not destroyed by int 21h/ah=2 so set them once
; before loop
print:
int 21h ; Print an 'X'
loop print ; Continue until loop is 0
negative:
mov sp, bp ; Restore stack pointer \
pop bp ; Restore BP register / Function epilogue
ret
endp example
我将其作为练习留给读者,以确定示例
PROC更改的所有寄存器,并根据作业中的要求保存/恢复它们。提示:在ARG指令之后PUSH它们,并在RET
之前以相反的顺序POP它们
关于assembly - 汇编中按值传递和按引用传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36293714/