文档章节

汇编总结:无符号除法,有符号除法,取余,无符号乘法,有符号乘法指令

guonaihong
 guonaihong
发布于 2015/10/07 21:04
字数 1538
阅读 2027
收藏 2

本文分为3个模块。

  1. 示例---该指令的示例

  2. 解释---为指令不好理解的地方

  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
    ret

3.2  编写函数,实现数字转字符串,函数原型如下:

char *int2str(int val, char *str, int base);

  base范围为2-36,可把val里的数字解释为2-36进制的字符串,并存入str中。

  val是输入。str是输出。

  汇编code:


   

© 著作权归作者所有

guonaihong

guonaihong

粉丝 6
博文 83
码字总数 27591
作品 1
徐汇
程序员
私信 提问
C语言基础学习运算符-基本算术运算符

基本算术运算符 C语言中用于基本算术运算的运算符有:+,-,,%,/。这些运算符的用法和你想像到的基本无异: 加法运算符 “+”使得它两侧的值被加到一起。 减法运算符“-”用它前面的数减去...

MayaTeacher
2016/09/14
19
1
计算机实验室之树莓派:课程 9 屏幕04

屏幕04 课程基于屏幕03 课程来构建,它教你如何操作文本。假设你已经有了课程 8:屏幕03 的操作系统代码,我们将以它为基础。 1、操作字符串 能够绘制文本是极好的,但不幸的是,现在你只能绘...

作者: Alex Chadwick
03/10
0
0
汇编跳转指令: JMP、JECXZ、JA、JB、JG、JL、JE、JZ、JS、JC、JO、JP 等

转自:http://www.cnblogs.com/del/archive/2010/04/16/1713886.html http://pan.baidu.com/s/1gVTSi 跳转指令分三类: 一、无条件跳转: JMP ;无条件跳转 二、根据CX、ECX寄存器的值跳转: JCX...

simpower
2018/10/25
987
0
Java拾遗:014 - 二进制、进制转换及位运算

二进制 二进制是计算机中广泛采用的一种数制,由0和1组成,进位规则为“逢二进一”,如:0001表示十进制中的1,0010表示十进制中的2。二进制拥有大量非学有用的特性,详情参考:百度百科:二...

一别丶经年
2018/08/02
121
0
(九)MySQL数据库-MySQL 运算符

版权声明:转载请注明原文地址 https://blog.csdn.net/Super_RD/article/details/89789123 (九)MySQL数据库-MySQL 运算符 我的系统版本为CentOS7.5,MySQL版本为5.7.26 算术运算符 在除法运...

Super_RD
05/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 不要在领导修风扇的时候打开电扇

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 :《Whats Up》 主唱妹子 Lina Perry 的嗓音实在太有力了,收放自如的自信才能唱出这么优秀的歌吧!#今日歌曲推荐# 《Whats Up》-...

小小编辑
今天
11
0
SpringBoot集成Elasticsearch并进行增删改查操作

一、创建工程 使用IntelliJ创建SpringBoot工程 SpringBoot版本为2.0.4 ElasticSearch为5.6.10 删掉蓝框中的文件(如上) 最后我们的目录结构(如下) 下面pom文件主要修改的是把spring boot从Int...

一字见心
今天
5
0
x001-版本介绍

python版本介绍 目前有2 和 3 有很多企业用的代码是2版本,随着技术的发展,以后用3的会成为大趋势 python3的安装 yum -y install wget gcc zlib-devel bzip2-devel openssl-devel ncurses-d...

侠客行之石头
今天
5
0
聊聊rocketmq的TransientStorePool

序 本文主要研究一下rocketmq的TransientStorePool TransientStorePool rocketmq-all-4.6.0-source-release/store/src/main/java/org/apache/rocketmq/store/TransientStorePool.java publi......

go4it
昨天
6
0
笔记

场外借贷, 质押 ,托管, 永续合约. 场外借贷,n签合同. 新功能 证券交易组负责中信证券机构及个人投资交易相关系统,服务机构及个人投资客户, 涉及到两融、期权、 期货、做市等境内境外创新业...

MtrS
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部