Skip to content

Latest commit

 

History

History
172 lines (143 loc) · 4.59 KB

ch05.md

File metadata and controls

172 lines (143 loc) · 4.59 KB

移动数据

汇编移动数据

定义数据

data段

data段是定义数据合适的位置

还有一种data段叫 .rodata 这个段内都是只读的,ro代表read-only

label和directive来定义data段的元素,label代表着该数据内存首地址的引用,除了label还需要定义多少个字节用来存储该数据,这需要一条汇编指令,由相应指令来指定.

相应指令为:

.ascii	字符串
.asciz	Null结尾字符串
.byte	字节
.double	双精度浮点数
.float	单精度浮点数
.int	32整型
.long	32整形
.octa	16字节整型
.quad	8字节整型
.short	16位整型
.single	单精度浮点型

一些例子:

output:
	.ascii "The processor Vedor Id is 'XXXXXXXXX'\n"
pi:
	.float 3.14159
values:
	.long 100,150,200,250,300

values类似于一个数组values代表100这个数,之后的数需要通过相对位移来访问

注意如果定义一个16位的整型确按照32位整型读的话,会照样读取4个字节的内存,即使是错误的值

定义静态标记

data段是用来定义变量的,但是也可以定义静态标记,类似于C里面的宏

.equ factor,	3
.equ LINUX_SYS_CALL, 0x80

这些值都是无法改变的,引用这些静态数据只要加一个美元符号就行

movl $LINUX_SYS_CALL,	%rax

bss段

定义生的内存段,用来为将来会用到的数据保留位置

.comm 为初始化的内存段 .lcomm 未初始化的本地内存段 形式是*.comm symbol,length* symbol是分配内存的标记,length是内存字节为单位的长度

.section .bss
.lcomm buffer,10000

bss的内容不会存储在可执行件里.上面这段对可执行为件大小不会有较大影响,但是换成 data的话就会暂居位置. fill指令会为一段内存自动填充值,用0.

# sizetest1.s - A sample program to view the executable size
.section .data
buffer:
.fill 10000
.section .text
.globl _start
_start:
movq $60, %rax
movq $0, %rdi
syscall

移动数据

MOV istructio is used as a general-purpose mover.

The MOV instruction formats

movx source,destination,source和destination可以是内存地址,在内存中的数据,之前定义的数据,还有寄存器.

x代表操作数的大小 q 64bit l 32bit w 16bit b 8bit 所以把RAX寄存器的值移动到RBX寄存器就是movq %rax,%rbx 16位的是movw %ax,%bx 有一些使用MOV的规则,先随意贴一下,以后再解释

 An immediate data element to a general-purpose register
 An immediate data element to a memory location
 A general-purpose register to another general-purpose register
 A general-purpose register to a segment register
 A segment register to a general-purpose register
 A general-purpose register to a control register
 A control register to a general-purpose register
 A general-purpose register to a debug register
 A debug register to a general-purpose register
 A memory location to a general-purpose register
 A memory location to a segment register
 A general-purpose register to a memory location
 A segment register to a memory location

使用带下标的内存位置

格式base_address(offset_address,index,size),数据会被定位于base_address + offset_address + index * size

使用寄存器寻址

可以通过美元符可以获取数据的地址,例如movq $values, %edi

4(%edi) 表示4个自己之后的地址.

条件Move指令

下次解释,很多不需要控制流而依靠单条指令实现条件Move的。

交换数据

一搬交换数据要写3行带个temp,但是有些集成的指令就能做到.

栈是后进先出的数据结构,有push和pop操作

栈如何工作

栈就先不解释了,栈底对应的是内存的顶部,push要栈顶指针-1,pop是栈顶指针+1 push,pop操作也有类似的movx操作,x表示数据的大小 可以用print/d 和x/x 来观察变化堆栈的变化 特别是print/x $esp 看看栈顶指针的变化

#pushpop.s - An example of using the PUSH and POP instructions
.section .data
data:
	.int 125
.section .text
.globl _start
_start:
	nop
	movq $24420,%rcx
	movw $250,%bx
	pushq %rcx
	pushw %bx push data
	push $data
	pop  %rax
	pop %rax
	popw %ax
	popq %rax
	mov $60 ,%rax
	mov $0  ,%rdi
	syscall

PUSH和POP所有寄存器

PUSHA/POPA	Push or pop all of the 16-bit general-purpose registers
PUSHAD/POPAD	Push or pop all of the 32-bit general-purpose registers
PUSHF/POPF	Push or pop the lower 16 bits of the EFLAGS register

手动操作RSP和RBP寄存器

RSP就是栈顶指针可以随意调用这个寄存器,RSP是基于RBP的相对位置方位栈的.

有效利用内存访问

//TODO

总结

熟悉移动指令和一般寄存器