assembly - 堆栈参数在使用 C 调用约定的程序集中消失

标签 assembly x86 libc calling-convention gnu-assembler

我目前正在编写一些 x86 汇编代码,并使用 asld 将其与 glibc 链接。

    .section .data

str1:
    .asciz "\n"

str3:
    .asciz "Hello"

str4:
    .asciz "Goodbye"

str5:
    .asciz "Guten Tag!"

str6:
    .asciz "Guten Morgen!"


    .section .bss
    .section .text
    .globl _start

_start:
    call main
    movl %eax, %ebx
    movl $1, %eax
    int $0x80

# void writeLine(char*);

    .type writeLine, @function
writeLine:
    pushl %ebp
    movl %esp, %ebp
    movl $str1, %ecx
    pushl %ecx
    movl 8(%ebp), %ecx
    pushl %ecx
    call strcat
    movl %eax, %ecx
    pushl %ecx
    call puts
    popl %ebx
    .leaver1:
    movl %ebp, %esp
    popl %ebp
    ret

    .type main, @function
main:
    pushl %ebp
    movl %esp, %ebp
    movl $str3, %ecx
    pushl %ecx
    call writeLine
    popl %ebx
    movl $str4, %ecx
    pushl %ecx
    call writeLine
    popl %ebx
    movl $str5, %ecx
    pushl %ecx
    call writeLine
    popl %ebx
    movl $str6, %ecx
    pushl %ecx
    call writeLine
    popl %ebx
    .leaver3:
    movl %ebp, %esp
    popl %ebp
    ret

与预期输出相关的问题是:

Hello
Goodbye
Guten Tag!
Guten Morgen!

我得到:

Hello
Guten Tag!

通过一些更深入的调试,当我像这样执行 printf 时,参数似乎正在消失:

pushl 8(%ebp)   # Argument for writeLine
pushl $str7     # "Argument for writeLine: %s\n"
call printf     # printf();

它将“消失”参数显示为空,如:

# should be "Goodbye"
Argument for writeLine: 

同样,当我以 %d 格式打印参数时,我最终得到一个常量,该数字仅随字符串 (str3, str4 等)我路过。

示例:134525414

我还尝试将它与 gcc (gcc -m32 -S main.c) 编译的程序进行比较,该程序应该做完全相同的事情,除了 gcc -生成的东西我快速查看代码找不到任何东西。

看来,我的论点正在消失。

最佳答案

strcat(str3, str1) 通过复制 str1 的字节将 str1 连接到 str3 的末尾从 str3 的终止空字节开始进入内存。因此 str3 的终止空值被字符 '\n' 覆盖,并且新的终止空值被写入后续字节。但是你猜怎么着:紧跟在 str3 的终止 null 之后的字节是 str4 的第一个字节。所以你刚刚用空字节覆盖了 str4 的第一个字节。因此,当您稍后打印它时,它的行为就像一个空字符串。

您可以在每个字符串之间添加一个额外的字节空间来避免这种情况。但更广泛地说,writeLine 函数修改它传递的字符串并不是真正明智的,因此更好的计划是重新设计它,这样它就不需要这样做了。例如,您可以通过一次调用 puts 来写入传递的字符串(它已经附加了一个换行符),如果您想要一个额外的换行符,请单独调用 putc .

关于assembly - 堆栈参数在使用 C 调用约定的程序集中消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68461236/

相关文章:

assembly - 如何同时使用 SSE2 和 PREFETCHh 指令?

c - 在 GCC 中每行列出一个目录内所有子文件夹和文件的完整路径

assembly - AOSP 非显而易见的 syscall() 实现

linux - 加载共享库 libc.so.6 时出现 mingetty 错误

xcode - 当我们在 swift 项目中遇到运行时错误时,为什么 Xcode 将我们发送到汇编语言的 Thread 输出?重点是什么 ?

assembly - Assembly x86 Irvine 中的链表

c - 为什么编译器要在栈上腾出空间

x86 - 设置、清除 OF 和 TF 标志的汇编指令

assembly - 如何在不污染缓存的情况下从内存加载值?

c++ - 内联汇编代码无法在 Visual C++ 2010 Express 中编译