文章目录
定义数据
数据段
.data 和 .rodata
数据类型:
* ascii 字符串
* asciz 0结束的字符串
* byte 字节值
* double 双精度浮点数
* float 单精度浮点数
* int 32位整数
* long 32位整数
* octa 16位整数
* quad 8位整数
* short 16位整数
* single 单精度浮点数
示例:
.section .data
msg:
.ascii "this is a test message"
factors:
.double 37.45, 45.33, 12.30
height:
.int 54
length:
.int 62,35,47
定义静态符号
示例:
.equ factor, 3
.equ LINUX_SYS_CALL, 0x80
movl $LINUX_SYS_CALL, %eax
bss 段
命令:
* comm 声明一段未初始化的内存区域
* .lcomm 生命一段本地的未初始化的内存区域(不能被其他文件访问)
格式:
.comm sysbol, length
示例:
.section .bss
.lcomm buffer, 10000
移动数据
移动命令
- 格式:
movx source, destination
x标识操作的位
l 32位
w 16位
b 8位 - 规则:
- 立即数到一般寄存器
- 立即数到内存单元
- 一般寄存器到另外一个一般寄存器
- 一般寄存器到段寄存器
- 段寄存器到一般寄存器
- 一般寄存器到段寄存器
- 控制寄存器到一般寄存器
- 一般寄存器到调试寄存器
- 调试寄存器到一般寄存器
- 内存单元到一般寄存器
- 内存单元到段寄存器
- 一般寄存器到内存单元
- 段寄存器到内存单元
- 示例:
#movtest2.s - An example of moving register data to memory
.section .data
value:
.int 1
.section .text
.globl _start
_start:
nop
movl $100, %eax
movl %eax, value
movl $1, %eax
movl $0, %ebx
int $0x80
- 调试
- as -o movtest2.o -gstabs movtest2.s
- ld -o movtest2 movtest.o
- gdb -q movtest2
- break *_start+1
- run
- x/d &value
- s
- s
- x/d &value
使用索引访问内存
- 格式:
base_address(offset_address, index, size) - 示例:
# movtest3.s - Another example of using indexd memory locations
.section .data
output:
.asciz "The value is %d\n"
values:
.int 10, 15, 20,25,30,35,40,45,50,55,60
.section .text
.globl _start
_start:
nop
movl $0, %edi
loop:
movl values(, %edi, 4), %eax
pushl %eax
pushl $output
call printf
addl $8, %esp
inc %edi
cmpl $11, %edi
jne loop
movl $0, %ebx
movl $1, %eax
int $0x80
- 执行
- as -o movtest3.o movtest3.s
- ld -dynamic-linker /lib/ld-linux.so.2 -lc -o movtest3 movtest3.o
使用寄存器间接地址访问
- 格式:
- mov $values, %edi 将values的地址存入edi
- mov %ebx, (%edi) 将ebx的值存入edi所存的内存中
- 示例:
#movtest4.s - An example of indirect addressing
.section .data
values:
.int 10, 15, 20, 25, 30, 35, 40, 45, 55, 60
.section .text
.globl _start
_start:
nop
movl values, %eax
movl $values, %edi
movl $100, 4(%edi)
movl $1, %edi
movl values(, %edi, 4), %ebx
movl $1, %eax
int $0x80
条件mov指令
- 格式:
cmovx source, destination
x代表跳转条件的字符
* CF 进位标识
* OF 溢出标识
* PF 奇偶标识
* SF 正负标识
* ZF 零标识
无符号数跳转
指令 | 描述 | 符号位 |
---|---|---|
CMOVA/CMOVNBE | 大于或者不小于等于 | (CF or ZF) = 0 |
CMOVAE/CMOVNB | 大于等于或者不小于 | CF=0 |
CMOVNC | 没有进位 | CF=0 |
CMOVVB/CMOVNAE | 小于 | CF=1 |
CMOVC | 有进位 | CF=1 |
CMOVBE/CMOVNA | 不大于 | (CF or ZF) = 1 |
CMOVE/CMOVZ | 等于 | ZF=1 |
CMOVNE/CMOVNZ | 不等于 | ZF=0 |
CMOVP/CMOVPE | 字节1为偶数个 | PF=1 |
CMOVNP/CMOVPO | 字节1为奇数 | PF=0 |
有符号数跳转
指令 | 描述 | 符号位 |
---|---|---|
CMOVGE/CMOVNL | 大于等于 | (SF xor OF)=0 |
CMOVL/CMOVNGE | 小于 | (SF xor OF) = 1 |
CMOVLE/VMOVNG | 小于等于 | ((SF xor OF) or ZF) = 1 |
CMOVO | 溢出 | OF=1 |
CMOVNO | 没有溢出 | OF=0 |
CMOVS | 正数 | SF=1 |
CMOVNS | 非正 | SF=0 |
使用CMOV指令
#cmovtest.s - An example of the CMOV instructions
.section .data
output:
.asciz "The largest value is %d\n"
valuse:
.int 105, 235, 61, 315, 134, 221, 53, 145, 117, 5
.section .text
.globl _start
_start:
nop
movl values, %ebx
movl $1, %edi
loop:
movl values(, %edi, 4), %eax
cmp %ebx, %eax
cmova %eax, %ebx
inc %edi
cmp $10, %edi
jne loop
pushl %ebx
pushl $output
call printf
addl $8, %esp
pushl $0
call exit
交换数据
数据交换指令
* XCHG 交换两个寄存器或者一个寄存器一个内存单元
* BSWAP 反转32为寄存器的字节顺序
* XADD 交换两个数并将和存储在目的操作数
* CMPXCHG 比较交换
* CMPXCHG8B 比较交换两个64位数
使用数据交换指令
# bubble.s - An example of the XCHG instruction
.section .data
values:
.int 105, 235, 61, 315, 134, 221, 53, 145, 117, 5
.section .text
.globl _start
_start:
movl $values, %esi
movl $9, %ecx
movl $9, %ebx
loop:
movl (%esi), %eax
cmp %eax, 4(%esi)
jge skip
xchg %eax, 4(%esi)
movl %eax, (%esi)
skip:
add $4, %esi
dec %ebx
jnz loop
dec %ecx
jz end
movl $values, %esi
mov %ecx, %ebx
jmp loop
end:
movl $1, %eax
movl $0, %ebx
int $0x80
栈
栈是如何工作的
出栈和入栈
*语法:
pushx source
pop destination
- 将所有的寄存器入栈出栈
- PUSHA/POPA 将所有的16位一般寄存器入栈/出栈
- PUSHAD/POPAD 将所有的32位寄存器入栈/出栈
- PUSHF/POPF 将16位的符号寄存器入栈/出栈
- PUSHFD/POPFD 将32位的符号寄存器入栈/出栈