Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 带参数的函数调用_Assembly_X86_X86 16 - Fatal编程技术网

Assembly 带参数的函数调用

Assembly 带参数的函数调用,assembly,x86,x86-16,Assembly,X86,X86 16,我正在努力创建函数并在汇编中调用它们 函数gfx\u draw\u h(颜色,x\u 1,y\u 1,x\u 2)应该从(x\u 1,y\u 1)到(x\u 2,y\u 1)绘制一条直线,但我无法获取x\u 2的值,以与gfx\u draw\h中的当前位置进行比较。重复 另外,另一段代码是否正确(没有堆栈损坏) 这是我的代码: BITS 16 ; ----------------------------------------------------------------------

我正在努力创建函数并在汇编中调用它们

函数
gfx\u draw\u h(颜色,x\u 1,y\u 1,x\u 2)
应该从
(x\u 1,y\u 1)
(x\u 2,y\u 1)
绘制一条直线,但我无法获取
x\u 2
的值,以与
gfx\u draw\h中的当前位置进行比较。重复

另外,另一段代码是否正确(没有堆栈损坏)

这是我的代码:

    BITS 16

; ----------------------------------------------------------------------

_start:
    mov ax, 07C0h
    add ax, 288
    mov ss, ax              ; SS = stack space
    mov sp, 4096            ; SP = stack pointer

    mov ax, 07C0h
    mov ds, ax              ; DS = data segment

    call gfx_init

    push 50                 ; x_2
    push 30                 ; y_1
    push 30                 ; x_1
    push 1000b              ; color

    call gfx_draw_h

    add esp, 16

    jmp $                   ; infinite loop

; ----------------------------------------------------------------------
; Initializes graphics.
;
; Sets the video mode.
;
; INPUT:
;   none
;
; OUTPUT:
;   none
;
gfx_init:
    mov ah, 00h             ; set video mode
    mov al, 12h             ; AL = graphical mode
    int 10h                 ; INT 10h / AH = 00h
    ret

; ----------------------------------------------------------------------
; Draws a horizontal line.
;
; INPUT:
;   color
;   x_1
;   y_1
;   x_2
;
; OUTPUT:
;   none
;
gfx_draw_h:
    pop ax                  ; color
    pop cx                  ; x
    pop dx                  ; y

    mov ah, 0Ch             ; change color for a single pixel

.repeat:
    cmp cx, [ebp + 20]      ; !!! THIS IS THE ISSUE !!!
    je  .done

    inc cx
    int 10h

    jmp .repeat

.done:
    ret

; ----------------------------------------------------------------------

times 510 - ($ - $$) db 0   ; padding with 0 at the end
dw 0xAA55                   ; PC boot signature
因为这是16位代码,所以在堆栈上推送4个参数只需要弹出8个字节

gfx_draw_h:
 pop ax                  ; color
 pop cx                  ; x
 pop dx                  ; y
由于gfx_draw_h是一个子例程(它是
call
ed),因此堆栈上有一个返回地址。您的第一个
pop-ax
将删除此项!您可以编写以下内容:

gfx_draw_h:
 mov bp, sp
 mov ax, [bp+2] ;color
 mov cx, [bp+4] ;x
 mov dx, [bp+6] ;y
按照此逻辑更改问题行,如(不要使用EBP!):


在用
sp
覆盖bp之前,您忘记了按bp
。现代调试器根本不需要堆栈框架,因此您可以跳过这一部分,特别是对于没有修改
sp
@PeterCordes的叶函数,我并没有真正忘记
push bp
,而是尽量使其尽可能简单。既然OP不想推送任何寄存器…@user3144770谢谢!我知道我以前做错了什么@PeterCordes我推bp的原因是什么?我在
mov-bp,sp
之前添加了
push-bp
,在
ret
之前添加了
pop-bp
。这就是你说的吗?@user5406450:是的。如果不保存
bp
,则会重击调用方的堆栈帧
bp
是所有abi中被调用方保存的寄存器:当函数返回时,
rbp
/
ebp
/
bp
必须具有调用方调用时的值。使用
bp
这种方式称为“堆栈帧”。正如我所说,这是可选的。现代gcc默认为
-fomit帧指针
,释放出
rbp
,用作另一个通用寄存器。在堆栈上具有可变长度数组的函数(
intfoo[n];
)中,gcc仍将创建一个堆栈帧来引用本地变量。谷歌堆栈帧。恐怕16位寄存器
[sp]
不是有效地址。我们必须在16位代码中使用堆栈帧!
gfx_draw_h:
 mov bp, sp
 mov ax, [bp+2] ;color
 mov cx, [bp+4] ;x
 mov dx, [bp+6] ;y
cmp cx, [bp + 8]      ; !!! THIS IS THE ISSUE !!!