C指针原理(44)-汇编基础

AT&T汇编语语言中的数据段与数据类型

.data段定义的数据元素保留在内存中能够被指令读取和写入;
.rodata段定义的数据元素只读;

.data与.rodata段的数据类型:

  1. .ascii 代表文本字符串类型
  2. .asciz 代表以空字符结尾的文本字串,在C中以空代表串的结尾
  3. .byte 代表一个字节值
  4. .double 双精度浮点数
  5. .float 单精度浮点数
  6. .int 代表32位整数
  7. .long 代表32位整数IA-32
  8. .octa 代表16字节整数
  9. .quad 代表8字节整数
  10. .short 代表16位整数
  11. .single 单精度浮点数 32位

同时可以使用.fill自动创建10000个数据元素,默认为每个字段创建一个字长,并使用零填充它。

在.data与.rodata段中定义的数据将从内存地址由低到高排列。编写一段简单的汇编代码

dp@dp:~ % cat test.s

.section .data

mybuffer:

.fill 100

.section .rodata

mytext:

.ascii “abcde”

val1:

.byte 'a'

val2:

.byte 'b'

.byte 'c'

.section .text

.globl _start

_start:

movl mytext,%eax

movl val1,%ebx

dp@dp:~ %

从对上面程序的反汇编可看出,内存地址从低到高放置了mytext(0804807f )、val1(08048084 )、val2(08048085)、mybuffer。

dp@dp:~ % objdump -D test

test: file format elf32-i386-freebsd

Disassembly of section .text:

08048074 <_start>:

8048074:a1 7f 80 04 08 mov 0x804807f,%eax

8048079:8b 1d 84 80 04 08 mov 0x8048084,%ebx

Disassembly of section .rodata:

0804807f :

804807f:61 popa

8048080:62 63 64 bound %esp,0x64(%ebx)

8048083:65 gs

08048084 :

8048084:61 popa

08048085 :

8048085:62 .byte 0x62

8048086:63 .byte 0x63

Disassembly of section .data:

08049088 :


.bss段定义的数据元素为未初始化的变量,在运行时对其进行初始化。

可分为数据通用内存区域和本地通用内存区域

本地通用内存区域不能从本地汇编代码之外进行访问。

.text段存放代码

在代码段中用“;”表示注释

汇编代码如下:

dp@dp:~ % cat test1.s

.section .rodata

output:

.asciz "the number is %d\n"

.section .data

value:

.int 0,0,0,0,0,0,0,0,0,0

.section .text

.globl main

main:

movl $0,%ecx

loopset:

;基地址(存在寄存器中的偏移地址,存在寄存器中的数据元素索引,存在寄存器中的数据元素大小)

   movl %ecx,value(,%ecx,4)

   inc %ecx

   cmpl $10,%ecx

   jne loopset

movl $0,%ecx

loopprint:

   movl value(,%ecx,4),%eax

   pushl %ecx

   pushl %eax

   pushl $output

   call printf

   add $8,%esp

   popl %ecx

   inc %ecx

   cmpl $10,%ecx

   jne loopprint

编译并运行

dp@dp:~ % gcc -o test1 test1.s

dp@dp:~ % ./test1

the number is 0

the number is 1

the number is 2

the number is 3

the number is 4

the number is 5

the number is 6

the number is 7

the number is 8

the number is 9

上述代码 ,先在.data可读写区域放置10个初始值为0的int值,然后在程序中通过loopset标记和jne语句完成一个循环,将它们的值依次赋值为0到9,最后通过loopprint标记和jne语句完成循环,调用c库的print语句将这些数输出。

inc表示自增1,而dec表示自减1 。

栈是由高地址向低地址增长的,当栈增加内容,将导致栈顶指针减少,否则,导致栈顶指针增加

在print语句执行返回后,清空执行print在堆栈中的生成垃圾,add 8 , 8,%esp,抛弃为调用printf函数准备的参数 ,栈顶有ESP寄存器来定位,压栈的操作使得栈顶的地址减小,弹出的操作使得栈顶的地址增大,因此这里相当于直接弹出压入的2个%eax(指向需要输出的数据)和 8,output参数,前面有调用:

pushl %eax

pushl $output

在上面这2个压栈之前,还调用了

pushl %ecx

其作用在于,保存%ecx的值,因为c库的printf函数会破坏%ecx寄存器的值,一般使用堆栈来保存可能被破坏的值,执行完printf完毕后,再还原:popl %ecx

你可能感兴趣的:(设计与架构)