使用printf
代码
#cpuid2.s -- Using C labrary calls
.section .data
output:
.asciz "The processor Vender is '%s'\n"
.section .bss
.lcomm buffer, 12
.section .text
.globl _start
_start:
movl $0, %eax
cpuid
movl $buffer, %edi
movl %ebx, (%edi) //含义同cpuid.s,向%edi所指向的buffer内存
movl %edx, 4(%edi) //位置写入3个寄存器的内容,这3个寄存器存储了
movl %ecx, 8(%edi) //CPU厂商信息的字符串(12字节)
pushl $buffer //将buffer和output入栈,为printf提供参数
pushl $output
call printf //调用C的printf函数
addl $8, %esp //将堆栈指针回滚8个字节,达到清除printf参数的目的
pushl $0
call exit
.asciz是在定义字符串的时侯在字符串结尾加上空字符(即C语言的\0),这样做的目的是为了让printf能读懂字符串。
.lcomm是在本地内存区域中声明固定长度的未初始化数据,这里初始化了12个字节的空间。
程序里buffer和output内存位置的内容是要向printf传递的参数值:
一个是"The processor Vender is '%s'\n"字符串;
另外一个是由cpuid返回结果(在ebx,edx,ecx三个寄存器中)填充的buffer。
需要通过堆栈来传递参数,所以在程序中使用
pushl $buffer
pushl $output
将参数入栈,printf获取参数是自右向左,即先buffer后output,所以要把buffer后入栈。
参数入栈之后,用call指令调用printf。
exit的情况同上,使用了一个参数--常数0。
汇编
#as -o cpuid2.o cpuid2.s
采用了动态连接的方式,所以C函数没有包含在可执行程序中,需要由另外的程序在运行时加载,ld不知道这个程序在哪里,所以我们还得手动指定
动态链接
#ld -dynamic-linker /lib/ld-linux.so.2 -lc -o cpuid2 cpuid2.o
#./cpuid2
输出
The processor Vendor ID is 'GenuineIntel'
GDB调试
# gdb cpuid2
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-56.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/zhms/AS/chap04/cpuid2...done.
(gdb) break _start
Breakpoint 1 at 0x80481b8: file cpuid2.s, line 10.
(gdb) r
Starting program: /usr/zhms/AS/chap04/cpuid2
Breakpoint 1, _start () at cpuid2.s:10
10 movl $0, %eax
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.80.el6_3.6.i686
(gdb) i r
eax 0x0 0
ecx 0x0 0
edx 0x758470 7701616
ebx 0x767fc4 7765956
esp 0xbffff6c0 0xbffff6c0
ebp 0x0 0x0
esi 0xbffff6cc -1073744180
edi 0x80481b8 134513080
eip 0x80481b8 0x80481b8 <_start>
eflags 0x286 [ PF SF IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) s
11 cpu