AT&T汇编语言基础学习示例
来源:互联网 发布:软件系统测试方法 编辑:程序博客网 时间:2024/06/10 03:43
Linux内核中硬件相关的代码基本都是用AT&T汇编语言实现,最近决定系统学习一下,以下使用AT&T汇编语言编写的几个简单程序:
1. Hello World.
编译运行的结果:
# gcc -o hello hello.s
./hello
Hello, world
2. 简单的加减法:
编译运行结果:
# gcc -o math math.s
# ./math
300
100
编译运行结果:
# gcc -o array array.s
# ./array
1
2
3
6. 基本的位操作
编译并运行:
# gcc -o bitop bitop.s
# ./bitop
num is 2
num is 4
num is 2
num is 1
num is 1
num is 3
num is -2147483647
num is 3
num is 2
ZF is set
7. 函数调用实现fibonacci数列
编译运行结果:
# gcc -o finn finn.s
# ./finn
finn(10) = 55
1. Hello World.
点击(此处)折叠或打开
- .section .rodata
- hello:
- .asciz "Hello, world" # 定义打印字符串,存放在数据段中,ro表示只读;
- format:
- .asciz "%s\n" # 定义打印格式字符串,存放在数据段中;
- .section .text # 代码段定义main函数。
- .globl main
- main:
- pushl $hello # push第二个参数到栈中
- pushl $format # push第一个参数到栈中
- call printf # 调用printf("%s\n", &hello)
- addl $8, %esp
- pushl $0
- call exit # 调用exit(0)
# gcc -o hello hello.s
./hello
Hello, world
2. 简单的加减法:
点击(此处)折叠或打开
- .section .rodata
- a:
- .int 100
- b:
- .int 200
- .section .data
- c:
- .int 0
- format:
- .asciz "%d\n"
- .section .text
- .globl main
- main:
- movl b, %eax
- addl a, %eax
- movl %eax, c # c= a+ b = 300
- pushl c
- pushl $format
- call printf # printf("%d", c)
- addl $8, %esp
- movl b, %eax
- subl a, %eax
- movl %eax, c # c= a- b = 100
- pushl c
- pushl $format
- call printf # printf("%d", c)
- addl $8, %esp
- pushl $0
- call exit
# gcc -o math math.s
# ./math
300
100
3. if/else 判断
- # judge.s
- .section .rodata
- num:
- .int 1
- iszero:
- .asciz "num is 0\n"
- notzero:
- .asciz "num is not zero\n"
- .section .text
- .globl main
- main:
- cmp $0, num
- jz Yes
- No:
- pushl $notzero
- call printf
- addl $4, %esp
- jmp end
- Yes:
- pushl $iszero
- call printf
- addl $4, %esp
- end:
- pushl $0
- call exit
编译运行:
# gcc -o judge judge.s
# ./judge
num is not zero
4. while循环打印0~100
点击(此处)折叠或打开
- # while.s
- .section .data
- format:
- .asciz "%d\n"
- num:
- .int 0
- .section .text
- .globl main
- main:
- movl $0, num
- loop:
- movl num, %eax
- addl $1, %eax
- movl %eax, num
- pushl %eax
- pushl $format
- call printf
- addl $8, %esp
- cmp $100, num
- jnz loop
- pushl $0
- call exit
编译并运行:
# gcc -o while while.s
# ./while
0
1
2
...
100
5. 数组的访问
for循环打印数组中的元素
点击(此处)折叠或打开
- # array.s
- .section .rodata
- array:
- .int 1, 2, 3 # 定义数组
- format:
- .asciz "%d\n"
- .section .text
- .globl main
- main:
- movl $array, %edi # 保存array的地址
- for:
- pushl (%edi) # 间接寻址得到array中的元素
- pushl $format
- call printf
- addl $8, %esp
- addl $4, %edi # 得到array中下一个元素的地址
- cmp $format, %edi
- jnz for
- pushl $0
- call exit
# gcc -o array array.s
# ./array
1
2
3
6. 基本的位操作
点击(此处)折叠或打开
- .section .data
- num:
- .int 1
- format:
- .asciz "num is %d\n"
- zfstr:
- .asciz "ZF is set\n"
- .section .text
- .globl main
- main:
- # 1. 算术左移
- # a. 右边直接补0
- # b. 左边移除的位放在CF进位标志中
- sall num # num = 2
- pushl num
- push $format
- call printf
- addl $8, %esp
- # 2. 逻辑左移
- # a. 右边直接补0
- # b. 左边移除的位放在CF进位标志中
- shll num # num = 4
- pushl num
- push $format
- call printf
- addl $8, %esp
- # 3. 算术右移动
- # a. 左边补充符号位
- # b. 右边移除的位放在CF进位标志中
- sarl num # num = 2
- pushl num
- push $format
- call printf
- addl $8, %esp
- # 4. 逻辑右移动
- # a. 左边补充符号位
- # b. 右边移除的位放在CF进位标志中
- shrl num # num = 1
- pushl num
- push $format
- call printf
- addl $8, %esp
- # 5. 与
- andl $1, num # num = 1
- pushl num
- push $format
- call printf
- addl $8, %esp
- # 6. 或
- orl $2, num # num = 3
- pushl num
- push $format
- call printf
- addl $8, %esp
- # 7. 循环右位移
- rorl num # num = 10000000 | 00000000 | 00000000 | 00000001
- pushl num
- push $format
- call printf
- addl $8, %esp
- # 8. 循环左位移
- roll num # num = 3
- pushl num
- push $format
- call printf
- addl $8, %esp
- # 9. 按位异或
- xorl $1, num # num = 2
- pushl num
- push $format
- call printf
- addl $8, %esp
- # 10. test并设置ZF
- movl $1, %eax
- test %eax, num
- jz setzf
- pushl $0
- call exit
- setzf:
- pushl $zfstr
- call printf
- pushl $0
- call exit
# gcc -o bitop bitop.s
# ./bitop
num is 2
num is 4
num is 2
num is 1
num is 1
num is 3
num is -2147483647
num is 3
num is 2
ZF is set
7. 函数调用实现fibonacci数列
点击(此处)折叠或打开
- # finn.s
- .section .rodata
- format:
- .asciz "finn(%d) = %d\n"
- .section .text
- .globl finn
- .type @function
- finn:
- pushl %ebp # (1). 保存原始的ebp
- movl %esp, %ebp #(2). 保存当前的esp
- pushl %ebx # (3). 保存要被修改的寄存器
- pushl %ecx
- # 当前的栈的状态:
- # +----------------+
- # | ... |
- # +----------------+
- # | ... |<-- 12(%ebp)
- # +----------------+
- # | arg1 | <-- 8(%ebp)
- # +----------------+
- # | return address | <-- 4(%ebp)
- # +----------------+
- # | old ebp | <--ebp
- # +----------------+
- # ^ | old ebx |
- # | +----------------+
- # memory | old ecx | <-- esp
- # addresses +----------------+
- movl 8(%ebp), %ebx #(4). 得到参数
- cmpl $2, %ebx #(5). 参数与2比较
- jle L1 # 参数 <= 2 则直接返回1, 否则计算finn(n-1)+ finn(n-2)
- subl $1, %ebx #(6). 得到(n-1)
- pushl %ebx
- call finn
- addl $4, %esp
- movl %eax, %ecx #(7). 得到finn(n-1)
- subl $1, %ebx #(8). 得到(n-2)
- pushl %ebx
- call finn
- addl $4, %esp
- addl %ecx, %eax #(9). 得到finn(n-1)+ finn(n-2)
- jmp RET
- L1:
- movl $1, %eax
- RET:
- popl %ecx
- popl %ebx
- movl %ebp, %esp # (10). 得到(2)保存的esp
- popl %ebp # (11). 得到(1)保存的ebp
- ret
- .globl main
- main:
- movl $10, %edi
- pushl %edi # 将参数放到栈中
- call finn
- addl $4, %esp
- pushl %eax
- pushl %edi
- pushl $format
- call printf
- addl $8, %esp
- pushl $0
- call exit
# gcc -o finn finn.s
# ./finn
finn(10) = 55
- AT&T汇编语言基础学习示例
- AT&T 汇编语言学习笔记
- AT&T 汇编语言学习笔记一
- AT&T 汇编语言学习笔记二
- AT&T汇编语言语法
- at&t汇编语言
- AT&T汇编语言语法
- AT&T汇编语言语法
- at&t linux汇编语言
- AT&T汇编语言
- AT&T汇编语言语法
- AT&T汇编语言总结
- AT&T汇编语言
- AT&T汇编语言学习:利用c库、文件读写
- AT&T汇编学习总结一-汇编语言前言准备
- AT&T汇编学习总结二-汇编语言程序范例
- AT&T汇编语言语法
- AT&T 汇编语言程序范例
- C++ STL map中的Key使用自定义类型
- 淘宝Tair分布式存储安装部署
- PHP关联数组的10个技巧
- 访问淘宝Tair的基础类型
- android activity与service通信
- AT&T汇编语言基础学习示例
- Linux内核学习系列---排队自旋锁
- 浅析淘宝网络通信库tbnet的实现
- 使用Tair时遇到pthread_join段错误问题解决
- 银行
- 图像检索:CEDD(Color and Edge Directivity Descriptor)算法
- 反汇编学习(4)-- 累加add循环
- Linux设备驱动之内存映射--mmap--转 .
- 斐波那契数列性质