【问题标题】:Why do we have to dereference stdout here?为什么我们必须在这里取消引用标准输出?
【发布时间】:2019-09-11 22:22:48
【问题描述】:

我正在尝试从程序集中调用fputs(str, stdout);

我为什么要push dword [stdout] 而不仅仅是push stdout

既然在 C 中我们不做 fputs(str, *stdout),为什么我们需要在汇编中取消引用 stdout

完整代码:

extern fputs
extern stdout

section .data
    hw: db "Hello World!", 10, 0

section .text
    global main

main:
    enter 0,0

    push dword [stdout]
    ;push stdout
    push hw
    call fputs

    leave
    mov eax, 0
    ret

【问题讨论】:

    标签: assembly x86 nasm calling-convention fputs


    【解决方案1】:

    您正在取消引用 asm 标签 stdout,相当于 C 中的 &stdout。它是内存中存储 FILE* 的静态位置。

    只有 C 数组类型的行为类似于 asm 标签,其中 C 中的名称是地址,而不是内容。

    另见Why in NASM do we have to use square brackets ([ ]) to MOV to memory location?


    在 NASM 中,裸符号名称是静态地址。在 C 中,一个简单的名称就是值

    (真正的 C 数组除外,其中的裸名是第一个元素的地址。)


    在 C 中,具有自动存储类的变量(即本地变量)也可以有名称,而不仅仅是静态的。在 asm 中,符号只能放在静态地址上。 (C 中的自动存储通常是 x86 asm 中的寄存器,或者如果您需要溢出/重新加载,则像 [ebp - 8] 这样的堆栈空间。堆栈地址不是链接时间常量,因此不能有标签。您可以相对于堆栈地址到 ESP 或 EBP。)

    具有动态存储的对象在 C 中不能有名称,只能由命名指针指向。

    【讨论】:

    • 所以stdin 的类型在汇编代码中是FILE**,对吧? C库导出的所有全局变量都是这样吗?
    • @happycoder97:不,这是错误的思考方式。在 NASM 中,一个裸符号名称 静态地址。在 C 中,无论是自动存储类还是静态存储类,裸名都是值。 (真正的数组除外,其中的裸名是第一个元素的地址。)(具有动态存储的对象在 C 中不能有名称,只能由命名指针指向。)
    猜你喜欢
    • 2011-09-03
    • 1970-01-01
    • 2021-12-12
    • 2012-05-12
    • 2020-07-17
    • 2014-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多