在汇编语言中使用C库函数

2021-07-18  本文已影响0人  wjundong

GNU 汇编: 第一个汇编程序 中, 利用Linux 系统调用将读到的 cpuid 显示到控制台上, 还有不使用系统调用的其他方法, 其中一种就是使用 C 库函数.

实例

demo.s

.section .data

output:
    .asciz "The processor Vender ID is '%s'\n"

.section .bss
    .lcomm buffer, 12

.section .text
.globl _start

_start:
    // 获取 CPU ID
    movl $0, %eax
    cpuid
    
    // 将 CPU ID 填充到 buffer
    movl $buffer, %edi
    movl %ebx,  (%edi)
    movl %edx, 4(%edi)
    movl %ecx, 8(%edi)

    // 调用C标准库 printf
    pushl $buffer
    pushl $output
    call printf
    addl $8, %esp
    push $0

    // 退出程序
    call exit

注意这里使用的是 .asciz 命令而不是 .ascii, 这是因为 C 语言的字符串需要以空字符结尾来判断字符串的结束.

命令 .comm.lcomm 用来声明通用内存区域, lcomm 表示该区域数据是静态的, 本地汇编代码之外的程序段无法访问该内存区域. 这里声明了 12 个字节的本地通用内存用于保存读取到的 cpuid.

为了把参数传给 C 函数 printf, 必须把它们压入堆栈. 这是使用 pushl 指令完成的. 参数放入堆栈的顺序和 printf 函数获取它们的顺序是相反的, 所以 buffer 先被放入, 然后是输出字符串, 在这些操作完成之后, 使用 call 指令调用 printf 函数.

指令 addl $8, %esp 将堆栈指针 sp 加 8, 其目的是为了清空调用 printf 函数时放入堆栈的参数, 使用相同的技术把返回值 0 压入堆栈供 C 函数 exit 使用.

连接 C 库函数

在 Linux 把 C 函数链接到汇编语言程序有两种办法:

  1. 静态链接
    静态链接把目标代码直接复制到应用程序的可执行文件中, 这样会使可执行文件巨大, 并且如果同时运行程序的多个实例, 因为每个实例都有自己相同函数的拷贝,这会造成内存浪费.
  2. 动态链接
    动态链接使用库的方式使程序员可以在应用程序中引用函数, 但是不会把代码拷贝到可执行文件中. 在程序运行时由操作系统调用动态链接库, 并且多个程序可以共享动态链接库.

使用 GCC 编译

也可以使用 gcc 编译器进行汇编和链接, 实际上, 对于本例子来说, 这会容易许多, 因为 gcc 编译器会自动链接必须的 C 库, 会自动设置正确的动态加载器.

上一篇下一篇

猜你喜欢

热点阅读