1. 简单程序hello world
#include <stdio.h>
int main(int argc, char** argv) {
printf("hello world!!\n");
int a = 0x123;
int b = 0x234;
int c = a + b;
printf("c is: 0x%x\n", c);
return 0;
}
编译gcc hello.c -o hello
1.1 gcc -S
gcc hello.c -S -o hello.s
查看hello.s内容cat hello.s
.file "hello.c"
.section .rodata
.LC0:
.string "hello world!!"
.LC1:
.string "c is: 0x%x\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
subq $32, %rsp
movl %edi, -20(%rbp)
movq %rsi, -32(%rbp)
movl $.LC0, %edi
call puts
movl $291, -4(%rbp)
movl $564, -8(%rbp)
movl -8(%rbp), %eax
movl -4(%rbp), %edx
leal (%rdx,%rax), %eax
movl %eax, -12(%rbp)
movl $.LC1, %eax
movl -12(%rbp), %edx
movl %edx, %esi
movq %rax, %rdi
movl $0, %eax
call printf
movl $0, %eax
leave
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.4.7-1ubuntu2) 4.4.7"
.section .note.GNU-stack,"",@progbits
1.2 objdump指令
1.2.1 objdump -s hello
显示所有section内容
objdump -s -j .rodata hello
hello: file format elf64-x86-64
Contents of section .rodata:
400688 01000200 68656c6c 6f20776f 726c6421 ....hello world!
400698 21006320 69733a20 30782578 0a00 !.c is: 0x%x..
只显示.rodata部分
1.2.2 objdump -S hello
objdump -S -j .rodata hello
hello: file format elf64-x86-64
Disassembly of section .rodata:
0000000000400688 <_IO_stdin_used>:
400688: 01 00 02 00 68 65 6c 6c 6f 20 77 6f 72 6c 64 21 ....hello world!
400698: 21 00 63 20 69 73 3a 20 30 78 25 78 0a 00 !.c is: 0x%x..
各段含义
汇编中bss,data,text,rodata,heap,stack,意义
bss段:
BSS段(bsssegment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文BlockStarted by Symbol的简称。BSS段属于静态内存分配。
data段:
数据段(datasegment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。
text段:
代码段(codesegment/textsegment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等
rodata段:
存放C中的字符串和#define定义的常量
ARM汇编
参数传递
当少于四个时,按从左到右的顺序依次放在r0,r1,r2,r3中;
当多于四个时,前四个放在r0,r1,r2,r3中,剩余的放在堆栈中,
最后一个参数先入栈,第五个参数最后入栈,即从右到左入栈
返回值
结果为32位时,通过R0返回
结果为64位时,r0放低32位,r1放高32位
BL
BL是arm汇编中用来调用子程序的指令,它把BL后面一条指令的地址放到R14寄存器里,R15寄存器(PC当前指针地址)就设置成要跳往的地址。这样在这个子程序返回时,再mov PC, R14就可以返回到BL后面的地址了
BEQ
BEQ指定是跳转指令,但是跳转要满足一定的条件,例:CMP R1,#0 BEQ Label 即当R1和0相等的时候程序跳到标号Label处执行。(BEQ执行后不调回去??)
LDR/STR
ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令。比如想把数据从内存中某处读取到寄存器中,只能使用ldr,比如:
ldr r0, 0x12345678
就是把0x12345678这个地址中的值存放到r0中。而mov不能干这个活,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,这个和x86这种CISC架构的芯片区别最大的地方。
LDR伪指令
ldr r0, =0x12345678
把0x12345678这个地址写到r0中
LDMIA
LDMIA R0! ,{R1,R2} 是指将R0指向的单元中的数据读出到R1,R2中
R1←[R0] R2←[R0+4]
BIC
位清除
BIC R0, R0, #0xF0000000 将R0高4位清零
BIC R1, R1, #0x0F 将R1低4位清0