AT&T汇编从一个获取cpuid程序了解汇编语言

it2023-02-28  86

文章目录

程序源码程序分析编译链接执行结果调试程序查看数据

程序源码

cpuid.s代码如下:

.section .data output: .ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n" .section .text .global _start _start: movl $0, %eax cpuid movl $output, %edi movl %ebx, 28(%edi) movl %edx, 32(%edi) movl %ecx, 36(%edi) movl $4, %eax movl $1, %ebx movl $output, %ecx movl $42,%edx int $0x80 movl $1,%eax movl $0,%ebx int $0x80

程序分析

首先在数据段,添加了一个string字符串。

.section .data output: .ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"

.ascii说明字符串是ascii码 其中的xx是符号用于后面的字符替换

接下来这三行可以看作是汇编程序的一个模板

.section .text .global _start _start:

声明了代码段以及程序的入口

接下来

movl $0, %eax cpuid

将0存入了eax寄存器中,这个0代表获取CPUID的参数

EAX值CPUID 输出0显示卖家ID的字符串1处理器的类型 家族等等信息2处理起的缓存信息3处理器的序列号4缓存配置5监控信息80000000h显示 额外的卖家ID字符串80000001h显示额外的处理器的类型 家族等等信息80000002h-80000004h显示额外的处理器名字的字符串

接下来运行完CPUID之后,需要收集返回值,返回值存在了3个寄存器中

movl $output, %edi movl %ebx, 28(%edi) movl %edx, 32(%edi) movl %ecx, 36(%edi) movl $4, %eax movl $1, %ebx movl $output, %ecx movl $42,%edx int $0x80

EAX 包含了系统调用的值 EBX 包含了要写入的文件描述符 ECX 包含了字符串的起始位置 EDX 包含了字符串的长度

编译链接

as -o cpuid.o cpuid.s ld -o cpuid cpuid.o

执行结果

$ ./cpuid The processor Vendor ID is 'GenuineIntel'

调试程序

如果你需要对汇编程序进行调试的话,就需要在编译的时候增加调试的选项,即增加-gstabs选项。

as -gstabs -o cpuid.o cpuid.s ld -o cpuid cpuid.o

接着使用gdb 进行调试

$ gdb cpuid GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-119.el7 Copyright (C) 2013 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-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/code/at/cpuid...done. (gdb)

在gdb中使用run命令

(gdb) run Starting program: /home/code/at/cpuid The processor Vendor ID is 'GenuineIntel' [Inferior 1 (process 17829) exited normally] (gdb)

可以看到,当输入run命令后,程序立即执行完毕了,为了让程序停止在某一个过程,就需要设置断点。

打断点可以参考下面的格式

break *label+offset

例如我们让程序停在第一行

(gdb) break *_start Note: breakpoint 1 also set at pc 0x4000b0. Breakpoint 2 at 0x4000b0: file cpuid.s, line 7. (gdb) r Starting program: /home/code/at/cpuid Breakpoint 1, _start () at cpuid.s:7 7 movl $0, %eax (gdb)

通过打上断点,我们发现程序没有继续往下执行,停留在了第7行中 可以使用next或者step命令进行单步执行

(gdb) next 8 cpuid (gdb) next 9 movl $output, %edi (gdb) step 10 movl %ebx, 28(%edi) (gdb) step 11 movl %edx, 32(%edi) (gdb)

使用cont命令使得程序继续执行

(gdb) cont Continuing. The processor Vendor ID is 'GenuineIntel' [Inferior 1 (process 17889) exited normally]

查看数据

数据命令描述info registers显示所有寄存器的值print显示某个具体的寄存器或者变量的值x显示某个内存位置上存储的值 (gdb) r Starting program: /home/code/at/cpuid Breakpoint 1, _start () at cpuid.s:7 7 movl $0, %eax (gdb) info registers rax 0x0 0 rbx 0x0 0 rcx 0x0 0 rdx 0x0 0 rsi 0x0 0 rdi 0x0 0 rbp 0x0 0x0 rsp 0x7fffffffe3f0 0x7fffffffe3f0 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x0 0 r12 0x0 0 r13 0x0 0 r14 0x0 0 r15 0x0 0 rip 0x4000b0 0x4000b0 <_start> eflags 0x202 [ IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 (gdb) s 8 cpuid (gdb) s 9 movl $output, %edi (gdb) info registers rax 0xd 13 rbx 0x756e6547 1970169159 rcx 0x6c65746e 1818588270 rdx 0x49656e69 1231384169 rsi 0x0 0 rdi 0x0 0 rbp 0x0 0x0 rsp 0x7fffffffe3f0 0x7fffffffe3f0 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x0 0 r12 0x0 0 r13 0x0 0 r14 0x0 0 r15 0x0 0 rip 0x4000b7 0x4000b7 <_start+7> eflags 0x202 [ IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0

程序刚刚运行时,EBX,ECX和EDX寄存器存储的值都是0。当运行cpuid指令之后,它们就存储了CPU卖家的ID 字符串。

如果使用print命令进行打印那么: print/d 可以以数字的形式显示 print/t 可以以二进制的形式显示 print/x 可以以十六进制的形式显示

如果使用x命令查看内存,可以使用如下的格式

格式: x /nfu <addr>

说明: x 是 examine 的缩写

n表示要显示的内存单元的个数

f表示显示方式, 可取如下值 x 按十六进制格式显示变量。 d 按十进制格式显示变量。 u 按十进制格式显示无符号整型。 o 按八进制格式显示变量。 t 按二进制格式显示变量。 a 按十六进制格式显示变量。 i 指令地址格式 c 按字符格式显示变量。 f 按浮点数格式显示变量。

u表示一个地址单元的长度 b表示单字节, h表示双字节, w表示四字节, g表示八字节

(gdb) break *_start Breakpoint 1 at 0x4000b0: file cpuid.s, line 7. (gdb) run Starting program: /home/code/at/cpuid Breakpoint 1, _start () at cpuid.s:7 7 movl $0, %eax (gdb) next 8 cpuid (gdb) next 9 movl $output, %edi (gdb) next 10 movl %ebx, 28(%edi) (gdb) next 11 movl %edx, 32(%edi) (gdb) next 12 movl %ecx, 36(%edi) (gdb) next 13 movl $4, %eax (gdb) x/42cb &output 0x6000ea: 84 'T' 104 'h' 101 'e' 32 ' ' 112 'p' 114 'r' 111 'o' 99 'c' 0x6000f2: 101 'e' 115 's' 115 's' 111 'o' 114 'r' 32 ' ' 86 'V' 101 'e' 0x6000fa: 110 'n' 100 'd' 111 'o' 114 'r' 32 ' ' 73 'I' 68 'D' 32 ' ' 0x600102: 105 'i' 115 's' 32 ' ' 39 '\'' 71 'G' 101 'e' 110 'n' 117 'u' 0x60010a: 105 'i' 110 'n' 101 'e' 73 'I' 110 'n' 116 't' 101 'e' 108 'l' 0x600112: 39 '\'' 10 '\n'
最新回复(0)