AT&T语法
$表示立即数,引用10进制数4,AT&T语法$4,Intel语法是4- AT&T语法在寄存器前加 % ,Intel语法不需要
- AT&T语法处理源操作数和目的操作数和Intel语法相反
AT&T: movl $4, %eax
Intel: mov eax, 4 - AT&T语法在助记符后使用一个单独的字符来引用操作中使用的数据长度, Intel 语法中数据长度被声明为单独的操作数
AT&T: movl $test, %eax
Intel: mov eax, dword ptr test - 长调用和跳转使用不同的语法定义段和偏移值
AT&T: ljmp$section,$offset
Intel: jmp section:offset
cpuid.s的编译
汇编器$: as -o cpuid.o cpuid.s
连接器$: ld -o cpuid cpuid.o
gdb是命令行调试器
objdump反汇编器 obj=>汇编$objdump -d test.o
gprof简档器 ,分析程序的执行和确定应用程序中的“热点”
$./demo
...
$gprof demo > gprof.txt
汇编程序的基础模板
.section .data
;.section命定义段 参数只能为 .data, .bss, .text
;.data 是初始化了的数据
.section .bss
;使用0(null)初始化,常用做汇编语言程中的缓冲区
.section .text
;文本段,所有汇编语言程序中都必须有文本段,数据段,bss段是可选的
.globl _start
;.globl命令声明外部程序可以访问的程序,如过编写外部汇编程序或C语言程序使用的一组工具,应该用.globl声明每个函数标签
_start:
;定义起始点,连接器必须知道指令码的起点,默认标签是_start,表明程序应该从这条指令开始执行
定义数据元素
.data 命令声明数据段
这个段中的任何元素都保留在内存中,并且可以被汇编程序中的指令读取和写入
.rodata 中数据段中的数据只能按照只读方式访问
数据段中定义元素需要一个标签和一个命令;
数据声明之后必须定义一个或多个默认值
| 命令 | 数据类型 |
|---|---|
| .ascii | 文本字符串 |
| .asciz | 以空字符结尾的文本字符串 |
| .byte | 字节值 |
| .double | 双精度浮点值 |
| .float | 单精度浮点值 |
| .int | 32位整数 |
| .long | 32位整数(同.int) |
| .octa | 16字节整数 |
| .quad | 8字节整数 |
| .short | 16位整数 |
| .single | 单精度浮点数(和.float相同) |
e.g.
pi:
.float 3.14159
sizes:
.long 100, 150, 200, 250, 300
定义静态符号
可以出现在数据段任何位置,建议在定义其他数据之前定义数据符号
.equ factor, 3
.equ LINUX_SYS_CALL, 0x80
使用$引用,movl LINUX_SYS_CALL, %eax
bss段
无需声明数据类型,只要声明为所需目的保留的原始内存部分即可
| 命令 | 描述 |
|---|---|
| .comm | 声明未初始化的数据的通用内存区域 |
| .lcomm | 声明未初始化的数据的本地通用内存区域 |
这两种区域工作情况类似;
本地通用内存区域 是 为不会从本地汇编代码之外进行访问的数据保留的
e.g.
.section .bss
.lcomm buffer, 10000
这条语句把10000字节的内存区域赋值给bufffer标签。在声明本地通用内存区域的程序之外的函数是不能访问的(不能在.globl命令中使用他们)
bss段中声明的数据不包含在可执行程序中。
.section .data
buffer:
.fill 1000
;.fill命令使汇编器自动创建1000个元素。默认为每个字段创建一个字节,并用0填充
helloworld hw.s
.section .data
word:
.ascii "Hello world!\n"
.section .text
.globl _start
_start:
movl $4, %eax
movl $1, %ebx
movl $word, %ecx
movl $13, %edx
int $0x80
movl $1, %eax
movl $0, %ebx
int $0x80
int $0x80 Linux系统调用
- write系统调用
EAX 系统调用值
EBX 要写入的文件描述符的值
ECX 包含字符串的开头
EDX 包含字符串的长度 - exit系统调用
EAX 系统调用值
EBX 退出代码值
编译:
giantpoplar@Lenovo:~/Desktop$ as -o hw.o hw.s
giantpoplar@Lenovo:~/Desktop$ ld -o hw hw.o
gdb调试
giantpoplar@Lenovo:~/Desktop$ as -gstabs -o hw.o hw.s
giantpoplar@Lenovo:~/Desktop$ ld -o hw hw.o
1.单步运行
giantpoplar@Lenovo:~/Desktop$ gdb hw
加断点 break *_start 断点在start后的第一条指令
next/step执行下一条程序
cont继续执行
2.查看信息
info registers 显示寄存器内容
print显示特定寄存器,来自程序变量的值
print/x $ebx
x 显示特定内存位置的值
cpuid.s
;cpuid.s
;Sample program to extract the processor Vendor ID
.section .data;cpuid.s
output:
.ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"
.section .text
.globl _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
$as -o cpuid.o cpuid.s
$ld -o cpuid cpuid.o
使用C库函数
;cpuid2.s
;View the CPUID Vendor ID string using C library calls
.section .datatext
output:
.asciz "The processor Vendor ID is '%s'\n"
.section .bss
.lcomm buffer, 12
.section .text
.globl _start
_start:
movl $0, %eax
cpuid
movl $buffer, %edi
movl %ebx, (%edi)
movl %edx, 4(%edi)
movl %ecx, 8(%edi)
pushl $buffer
pushl $output
call printf
addl $8, %esp
pushl $0
call exit
; .asciz在定义的字符串末尾添加空字符
; .lcomm buffer, 12 声名了12字节的缓冲区
; pushl 压栈,参数放入堆栈的顺序和printf函数获取他们的顺序是相反的
; call 指令调用printf函数
; addl 出栈8个字节
#连接 要使用32位的链接库
$as -o cpuid.o cpuid.s
$ld -dynamic-linker /lib/ld-linux.so.2 -o cpuid2 -lc cpuid.o
本文介绍了IA32汇编语言的基础,包括AT&T语法、数据段定义、C库函数的使用,以及如何通过汇编程序实现Linux系统调用如helloworld和cpuid。涉及的内容包括编译、调试和段如.data、.rodata、bss的使用。

1万+

被折叠的 条评论
为什么被折叠?



