如果我要在程序集中编写程序,那么这个HelloWorld汇编代码的哪些部分是必不可少的?

Con*_*nor 10 c linux x86 assembly

我有这个简短的你好世界计划:

#include <stdio.h>

static const char* msg = "Hello world";

int main(){
    printf("%s\n", msg);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我用gcc将它编译成以下汇编代码:

    .file   "hello_world.c"
    .section    .rodata
.LC0:
    .string "Hello world"
    .data
    .align 4
    .type   msg, @object
    .size   msg, 4
msg:
    .long   .LC0
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $16, %esp
    movl    msg, %eax
    movl    %eax, (%esp)
    call    puts
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
    .section    .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)

我的问题是:如果我在汇编中编写这个程序(而不是用C编写然后编译成汇编程序),这段代码的所有部分都是必不可少的吗?我理解装配说明,但有一些我不明白的部分.例如,我不知道.cfi*是什么,我想知道是否需要包含它来在程序集中编写这个程序.

zwo*_*wol 15

在这个平台上可以使用的绝对最低限度是

        .globl main
main:
        pushl   $.LC0
        call    puts
        addl    $4, %esp
        xorl    %eax, %eax
        ret
.LC0:
        .string "Hello world"
Run Code Online (Sandbox Code Playgroud)

但这打破了许多ABI要求.ABI兼容计划的最低要求是

        .globl  main
        .type   main, @function
main:
        subl    $24, %esp
        pushl   $.LC0
        call    puts
        xorl    %eax, %eax
        addl    $28, %esp
        ret
        .size main, .-main
        .section .rodata
.LC0:
        .string "Hello world"
Run Code Online (Sandbox Code Playgroud)

目标文件中的其他所有内容都是编译器没有尽可能紧密地优化代码,或者是要写入目标文件的可选注释.

.cfi_*指令,尤其是可选的注解.当且仅当在抛出C++异常时函数可能在调用堆栈上时,它们才是必需的,但它们在您可能想要从中提取堆栈跟踪的任何程序中都很有用.如果您要用汇编语言手工编写非平凡的代码,那么可能值得学习如何编写它们.不幸的是,它们的记录很少; 我目前没有找到任何我认为值得链接的东西.

这条线

.section    .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)

了解你是否正在手工编写汇编语言也很重要; 它是另一个可选的注释,但却是一个有价值的注释,因为它意味着"此对象文件中没有任何内容需要堆栈可执行".如果程序中的所有目标文件都有此注释,则内核不会使堆栈可执行,这会稍微提高安全性.

(为了表明你确实需要堆栈是可执行的,你可以"x"代替"".如果你使用它的"嵌套函数"扩展,GCC可能会这样做.(不要这样做.))

值得一提的是,在GCC和GNU binutils使用的"AT&T"汇编语法(默认情况下)中,有三种行:一行上有一个令牌,以冒号结尾,是一个标签.(我不记得标签中可出现哪些字符的规则.)第一个标记以点开头而不以冒号结尾的行是汇编程序的某种指令.其他任何东西都是汇编指令.


归档时间:

查看次数:

1149 次

最近记录:

8 年,5 月 前