《汇编语言》--程序范例
参考资料:
《汇编语言程序设计》 Richard Blum 著
一. 编写程序查看CPUID指令生成的厂商ID字符串
1 .section .data 2 output: 3 .ascii "The processor Vendor ID is 'xxxxxxxx'\n'" 4 .section .text 5 .globl _start 6 _start: 7 movl $0, %eax 8 cpuid 9 movl $output, %edi 10 movl %ebx, 28(%edi) 11 movl %edx, 32(%edi) 12 movl %ecx, 36(%edi) 13 movl $4, %eax 14 movl $1, %ebx 15 movl $output, %ecx 16 movl $42, %edx 17 int $0x80 18 movl $1, %eax 19 movl $0, %ebx 20 int $0x80
这部分代码包含很多汇编指令, 具体的用法后面章节会细细道来, 今天主要是利用这个示例来讲解整个汇编编译,运行,链接,调试以及连接C库函数
二. 下面对源码如何工作的进行简单讲解:
首先, 在数据段声明一个字符串
output:
.ascii "The processor Vendor ID is 'xxxxxxxx'\n'"
.ascii声明使用的是ASCII字符声明一个文本字符串,字符串被预定义并放在内存中,起始位置由output指示
下面是程序模板的段落,声明程序的指令码段和一般的起始标签:
.section .text
.globl _start
_start:
程序做的第一件事就是给EAX寄存器加载零值,然后运行CPUID指令:
movl $0, %eax
cpuid
EAX中的零值定义CPUID输出选项(厂商ID),CPUID运行之后,必须收集分散在三个输出寄存器中的指令响应
movl $output, %edi -> 创建一个指针声明变量output,output内存加位置加载到EDI寄存器中
接下来按照EDI指针,包含厂商ID字符串的三个寄存器的内容被放到内存数据中的正确位置,括号外的数字表示相对于output标签的放置数据的位置
数字和EDI寄存器中地址相加,就是值被写入的地址
注意:厂商ID 字符串按照奇怪的EBX EDX 和 ECX分散存放
movl %ebx, 28(%edi)
movl %edx, 32(%edi)
movl %ecx, 36(%edi)
在内存中放置好厂商ID字符串之后,就可以显示信息了:
movl $4, %eax
movl $1, %ebx
movl $output, %ecx
movl $42, %edx
int $0x80
使用系统调用(int $0x80)从linux 内核显示到控制台
编译链接:
as -o cpuid.o cpuid.s
ld -s -o cpuid cpuid.o
运行结果:The processor Vendor ID is 'GenuineIntel'
三. 调试程序
使用GDB,为了能够调试汇编代码,需要编译时候添加-gstabs选项
as -gstabs -o cpuid.o cpuid.s
ld -s -o cpuid cpuid.o
3.1 单步运行
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 Copyright (C) 2014 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 "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from cpuid...(no debugging symbols found)...done.
使用RUN指令运行
(gdb) run Starting program: /home/fly/smem-0.1/huibian/cpuid The processor Vendor ID is 'GenuineIntel.s[Inferior 1 (process 12863) exited normally]
基本调试命令与调试C类似,这里不做讲解了
3.2 查看数据
info register: 显示所有寄存器的值
print: 显示特定寄存器或者程序变量的值
x: 显示特定内存位置的内容
使用info reginster 查看指令如何影响所有寄存器是很方便的:
1 (gdb) info registers 2 rax 0x4 4 3 rbx 0x1 1 4 rcx 0x6000ec 6291692 5 rdx 0x2a 42 6 rsi 0x0 0 7 rdi 0x6000ec 6291692 8 rbp 0x0 0x0 9 rsp 0x7fffffffeb10 0x7fffffffeb10 10 r8 0x0 0 11 r9 0x0 0 12 r10 0x0 0 13 r11 0x200 512 14 r12 0x0 0 15 r13 0x0 0 16 r14 0x0 0 17 r15 0x0 0 18 rip 0x4000dc 0x4000dc <_start+44> 19 eflags 0x10202 [ IF RF ] 20 cs 0x33 51 21 ss 0x2b 43 22 ds 0x0 0 23 es 0x0 0 24 fs 0x0 0 25 gs 0x0 0