汇编总结:无符号除法,有符号除法,取余,无符号乘法,有符号乘法指令
2015-10-07 21:04
387 查看
本文分为3个模块。示例---该指令的示例解释---为指令不好理解的地方练习---为了更熟悉该指令1.1 有符号除法指令及取余example:在c语言里要完成 8 / 2的汇编指令如下:在c语言里要完成 8 % 2的汇编指令如下:
.section .text .global _start _start: movl $8, %eax #被除数是%edx:%eax 是这两个寄存器拼起来的%eax存放低位%edx存储高位 movl %eax, %edx shrl $31, %edx #根据符号位填充%edx寄存器 movl $2, %ecx idivl %ecx #%eax保存商 %edx保存余数上面的也是4个字节除法及取余运算示列,跟据所使用的类型不同(c语言有同类概念)还有如下变种:1个字节的除法及取余运算示例如下:
.section .text .global _start _start: movw $8, %ax #被除数是%ax寄存器 movb $2, %cl idivb %cl #除数可以是通用寄存器,这里的demo是%cl。%al存放商。%ah存放余数2个字节的除法及取余运算示例如下:
.section .text .global _start _start: movw $8, %ax #被除数是%dx:%ax 是这两个寄存器拼起来的%ax存放低位%dx存储高位 movw %ax, %dx shrw $15, %dx movw $2, %cx idivw %cx #%ax保存商 %dx保存余数8个字节的除法及取余运算示例如下:
.section .text .global _start _start: movq $8, %rax #被除数是%rdx:%rax 是这两个寄存器拼起来的%rax存放低位%rdx存储高位 movq %rax, %rdx shrq $63, %rdx movq $5, %rcx idivq %rcx #%rax保存商 %rdx保存余数1.2 下面的除数指令里为什么用右移指令操作%edx寄存器?
.section .text .global _start _start: movl $8, %eax #1 movl %eax, %edx #2 shrl $31, %edx #3 movl $2, %ecx #4 idivl %ecx #5上面的例子第2+3行其实根据被除数%eax里的符号将%edx设置为全零或者全一。这样一来,两个寄存器就拼成了64位的寄存器(%edx:%eax--被除数)1.3 无符号除法指令用法无符号除法指令和有符号除法指令差不多,只要把idiv换成div就行。2.1 有符号乘法指令example:在c语言里要完成 4 * 3的汇编指令如下:根据imul的操作数的个数不同可分为两种,一种是两个操作数。这时执行imull指令,结果存在第二个操作数里。另一种是一个操作数。这时候的结果保存到%edx:%eax两个寄存器。2.1.1 双操作数imul指令example:c语言要完成a = 3; a *= 4;可用如下指令完成同等效果
.section .text .global _start _start: movw $3, %cx imulw $4, %cx movl $3, %ecx imull $4, %ecx movq $3, %rcx imulq $4, %rcx注意:双操作数imul指令没有imulb版本的2.1.2 单操作数imul示例如下:1个字节的乘法运算示例如下:
.section .text .global _start _start: movb $0x7f, %al #被乘数需放至%al寄存器中 movb $4, %cl #乘数可为通用寄存器或者内存地址 imulb %cl #ah存储高位 al存储低位,可用ax引用结果2个字节的乘法运算示例如下:
.section .text .global _start _start: movw $0x7fff, %ax #被乘数需放至%ax寄存器中 movw $4, %cx #乘数可为通用寄存器或者内存地址 imulw %cx #dx存储高位 ax存储低位。结果保存在dx:ax两个寄存器中4个字节的乘法运算示例如下:
.section .text .global _start _start: movl $0x7fffffff, %eax #被乘数需放至%eax寄存器中 movl $4, %ecx #乘数可为通用寄存器或者内存地址 imull %ecx #edx存储高位 eax存储低位 结果保存在edx:eax两个寄存器中8个字节的乘法运算示例如下:
.section .text .global _start _start: movq $0x7fffffffffffffff, %rax #被乘数需放至%rax寄存器中 movq $4, %rcx #乘数可为通用寄存器或者内存地址 imulq %rcx #rdx存储高位 rax存储低位 结果保存在rdx:rax两个寄存器中2.2 无符号乘法指令用法无符号乘法和有符号乘法指令差不多,只要把imul换成mul就行。3.1 编写函数,实现字符串转数字。函数原型如下:
int str2int(const char *str, int base);base范围为2-36,可把str里的数组解释为2-36进制的数需要提供一定的进制猜测能力。当base为0时打开进制猜测能力。str以0b或0B开头,默认为2进制。以0开头默认为8进制。以0x或0X开头,默认为16进制,其余默认为10进制。str以'-'开头。base 为10时,认为是10进制的负数。其余进制?汇编code:
.equ SIGN_SIZE, 4 .equ SIGN, -4 #str2int(const char *str, int base) .section .text .global str2int .type str2int, @function str2int: pushq %rbp movq %rsp, %rbp subq $SIGN_SIZE, %rsp movl $1, SIGN(%rbp) #初始化返回值 movl $0, %eax #判断base的值 cmpl $0, %esi je str2int_init_base cmpl $2, %esi jl str2int_exit cmpl $36, %esi jg str2int_exit jmp str2int_skip_space str2int_init_base: movl $10, %r9d str2int_skip_space: movb (%rdi), %r8b cmpb $0, %r8b je str2int_exit cmpb $' ', %r8b je str2int_skip_space_next cmpb $'\r', %r8b je str2int_skip_space_next cmpb $'\n', %r8b je str2int_skip_space_next cmpb $'\t', %r8b je str2int_skip_space_next jmp str2int_sign str2int_skip_space_next: incq %rdi jmp str2int_skip_space str2int_sign: cmpb $'-', %r8b jne str2int_guess_hex incq %rdi movl $-1, SIGN(%rbp) str2int_guess_hex: cmpb $'0', %r8b jne str2int_check_base movl $8, %r9d incq %rdi movb (%rdi), %r8b cmpb $0, %r8b je str2int_exit cmpb $'b', %r8b je str2int_guess_hex_2 cmpb $'B', %r8b je str2int_guess_hex_2 cmpb $'x', %r8b je str2int_guess_hex_16 cmpb $'X', %r8b je str2int_guess_hex_16 jmp str2int_check_base str2int_guess_hex_2: movl $2, %r9d incq %rdi jmp str2int_check_base str2int_guess_hex_16: movl $16, %r9d incq %rdi str2int_check_base: cmpl $0, %esi jne str2int_cal movl %r9d, %esi str2int_cal: xorl %r9d, %r9d movb (%rdi), %r9b cmpb $0, %r9b je str2int_exit orb $0x20, %r9b #if (c >= 'a' && c <= 'z') cmpb $'a', %r9b jl str2int_cal_10 cmpb $'z', %r9b jg str2int_exit subb $'a', %r9b addb $10, %r9b jmp str2int_cal_next str2int_cal_10: #if (c >= '0' && c <= '9') cmpb $'0', %r9b jl str2int_exit cmpb $'9', %r9b jg str2int_exit subb $'0', %r9b str2int_cal_next: imull %esi, %eax addl %r9d, %eax incq %rdi jmp str2int_cal str2int_exit: imull SIGN(%rbp), %eax movq %rbp, %rsp popq %rbp ret3.2 编写函数,实现数字转字符串,函数原型如下:
char *int2str(int val, char *str, int base);base范围为2-36,可把val里的数字解释为2-36进制的字符串,并存入str中。val是输入。str是输出。汇编code:
相关文章推荐
- pat1033To Fill or Not to Fill (25)
- Blocks的总结
- NOIP2006 2k进制数
- Navicat For Mysql快捷键
- 安卓Jsoup解析
- 单例模式
- 【python】抄写爬淘宝已买到的宝贝的代码
- matlab中的sparse和full函数(稀疏矩阵和非稀疏矩阵之间的转换)
- 2015-10-8/9 weather
- Html直接打开word文档而不是提示下载
- C#Process多线程使用&&StartInfo空格处理方法
- 1到100的所有整数中出现多少次数字9
- 企业级开发开源搜录集
- JAVA 中的类和对象(1)
- NOIP2006 金明的预算方案
- Linux下安装eclipse的C/C++集成开发环境
- MVC与JavaWeb三层结构
- POJ 1456 Supermarket 并查集(想不到的思路)
- nginx网站重定向,日志切割
- 简易计算器