码迷,mamicode.com
首页 > 其他好文 > 详细

一段简单的汇编程序

时间:2015-06-21 09:17:18      阅读:110      评论:0      收藏:0      [点我收藏+]

标签:

.section .data
        < initialized data here >
.section .bss
        < uninitialized data here >
.section .text
.global _start
_start:
        < instruction code >

如上述代码所示,汇编程序通常包含3个段(section):

  1. data section
  2. bss section
  3. text section

GNU assembler使用.section语句来声明section。.section语句只带一个参数。

除定义section之外,还需要定义一个起始点。当程序转换成可执行代码时,linker必须知道执行代码的起始点。GNU assembler定义了一个默认的符号(label、identifier): _start。可以不使用_start作为起始点,但是需要在linker中加入-e参数。此外,还需要让该起始点在其他代码中可能看到,这就需要.global指令。

.global指令声明一个符号可以从其他程序中访问,如果你正在些一组需要被其他程序或者C程序访问的工具,那就需要在函数符号前添加.global指令。

一,一段简单程序

 1 # cpuid.s Print process Vendor ID, AT&T syntax
 2     .section .data
 3 output:
 4     .ascii "The processor Vendor ID is ‘xxxxxxxxxxxx‘\n"
 5     
 6     .section .text
 7     .global _start
 8 _start:
 9     movl $0, %eax
10     cpuid
11     movl $output,     %edi
12     movl %ebx,     28(%edi)
13     movl %edx,     32(%edi)
14     movl %ecx,     36(%edi)
15     movl $4,    %eax
16     movl $1,    %ebx
17     movl $output,    %ecx
18     movl $42,    %edx
19     int  $0x80
20     movl $1,    %eax
21     movl $0,    %ebx
22     int  $0x80

二,构建与执行

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

输出:

The processor Vendor ID is ‘GenuineIntel‘

注意:这里其实可以使用gcc, 但有个问题是GNU linker以_start作为起始点,而gcc会查找main符号。所以其实把代码中的_start改为main,就可以用gcc语句来编译:

.section .text
.global main
main:
gcc -o cpuid cpuid.s

 

三,代码分析

1, cpuid 指令

CPUID 指令一般用于处理器信息,把结果返回到寄存器中。具体如下:

EAX中存放查询码:

EAX值 CPUID输出
0 Vendor ID string, and maximum CPUID option value suppted
1 Processor type, family, model, and stepping information
2 Processor cache configuration
3 Processor serial number
4 Cache configuration(number of threads, cores, and physical properties
5 Monitor information
80000000h Extended vendor ID string and supported levels
80000001h Extended processor type, famlily, model, and stepping information
80000002h-80000004h Extended processor name string

 

 

 

 

 

 

 

根据EAX的查询码,CPUID会在EBX,ECX,EDX中存放不同的值,以上例中的0为例,即查询vendor string,CPUID会分别在EBX中返回最低的4字节,EDX总返回中间4字节,ECX中返回最高4字节。

2,系统调用-- int $0x80

linux kernel提供了一组系统调用,要使用这些系统需要使用int指令带一个0x80值来生成一个软中断,具体触发使用什么系统调用,取决于EAX中的值。

以write系统调用为例,EAX存放系统调用码4,EBX包含fd,ECX包含输出字符串起始地址,EDX包含输出字符串长度。

3,语句解释

.ascii "The processor Vendor ID is ‘xxxxxxxxxxxx‘\n"

.ascii 用于声明一段ASCII字符串。该字符串会在内存中以output符号标识的内存位置开始存放好。语句中众多‘x‘,只是些placeholder,用于被返回的值替换。

 6     .section .text
 7     .global _start
 8 _start:

这段代码不在赘述,在引言中已经说明过了。

9     movl $0, %eax
10    cpuid

CPUID指令,参见上文。

11     movl $output,     %edi
12     movl %ebx,     28(%edi)
13     movl %edx,     32(%edi)
14     movl %ecx,     36(%edi)

edi中存放output的值(指针),把CPUID返回的值依次写到字符串相应的偏移位置中(‘xxxxxxxxxxxx‘)。

15     movl $4,    %eax
16     movl $1,    %ebx
17     movl $output,    %ecx
18     movl $42,    %edx
19     int  $0x80

write系统调用,向fd 1(stdoutput)写出output。

20     movl $1,    %eax
21     movl $0,    %ebx
22     int  $0x80

系统调用码1(exit),ebx存放程序的退出码。

四,结束

这段简单程序的结构和语句的含义到此就结束了。这里再记一笔工具链相关的内容,以备来时查用。

as的调试参数: -gstabs

设置断点:可以通过label,源代码行数,变量达到某个具体值,函数执行次数到达某个具体值来设置断点。 用label设置断点的形式为: break *label+offset, 比如, break *_start

查看数据:

info registers Display the values of registers  
print Display the values of a spefic register or variable form the program

print/d,  print/t, print/x

x Display the contents of a specific memory location

x/nyz, (注,符号需要加&, 以表明是内存地址)

n is the numberof fields to display,

y is the format of the output:

  c for character, d for decimal, x for hexadecimal

z is the size of the field :

  b for byte, h for 16-bit word(half-word), w for 32-bit world

Q.E.D.

一段简单的汇编程序

标签:

原文地址:http://www.cnblogs.com/cudbuc/p/4591118.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!