Ubuntu x86-64汇编(4) 数值操作指令
整数乘法指令 Integer Multiplication
对于有符号数的乘法有特殊的规则, 因此无符号数乘法和有符号数乘法对应着不同的指令mul和imul. 乘法会产生两倍尺寸的数值结果, 即两个n-bit数相乘会产生2n-bit的数. 两个8bit数相乘会产生16bit的数. 对于乘法指令有许多变种, 例如对于带符号乘法, 一些指令能将结果裁剪至和源数值一样的尺寸.
无符号的乘法 Unsigned Multiplication
通常这种乘法的格式为
mul <src>
mul <op8>
mul <op16>
mul <op32>
mul <op64>
mul word [wVvar]
mul al
mul dword [dVar]
mul qword [qVar]
src运算数必须是寄存器或内存地址, 不能为立即数. 对于这样的单运算数乘法指令, 在执行时, 会使用A寄存器中对应尺寸的数值(al/ax/eax/rax). 分别对应8bit, 16bit, 32bit, 64bit尺寸的运算数. 乘法的结果会被放置在A寄存器以及D寄存器中. 下面的表格显示了不同尺寸下的无符号乘法及其结果
Byte: ax = al * <src>
Word: dx:ax = ax * <src>
Double: edx:eax = eax * <src>
Quad: rdx:rax = rax * <src>
这样的结果位置组合, 是由于要向下兼容早先的版本, 会让人有些困惑.
代码例子
bNumA db 42
bNumB db 73
wAns dw 0
wAns1 dw 0
wNumA dw 4321
wNumB dw 1234
dAns2 dd 0
dNumA dd 42000
dNumB dd 73000
qAns3 dq 0
qNumA dq 420000
qNumB dq 730000
dqAns4 ddq 0 ; wAns = bNumA^2 or bNumA squared
mov al, byte [bNumA]
mul al ; result in ax
mov word [wAns], ax ; wAns1 = bNumA * bNumB
mov al, byte [bNumA]
mul byte [bNumB] ; result in ax
mov word [wAns1], ax ; dAns1 = wNumA * wNumB
mov ax, word [wNumA]
mul word [wNumB] ; result in dx:ax
mov word [dAns1], ax
mov word [dAns1+2], dx ; qAns3 = dNumA * dNumB
mov eax, dword [dNumA]
mul dword [dNumB] ; result in edx:eax
mov dword [qAns3], eax
mov dword [qAns3+4], edx ; dqAns4 = qNumA * qNumB
mov rax, qword [qNumA]
mul qword [qNumB] ; result in rdx:rax
mov qword [dqAns4], rax
mov qword [dqAns4+8], rdx
带符号数乘法 Signed Multiplication
带符号数的乘法允许更大范围的运算数和尺寸. 通常的格式为
imul <src>
imul <dest>, <src/imm32>
imul <dest>, <src>, <imm32>
imul <op8>
imul <op16>
imul <op32>
imul <op64>
imul <reg16>, <op16/imm>
imul <reg32>, <op32/imm>
imul <reg64>, <op64/imm>
imul <reg16>, <op16>, <imm>
imul <reg32>, <op32>, <imm>
imul <reg64>, <op64>, <imm>
imul ax, 17
imul al
imul ebx, dword [dVar]
imul rbx, dword [dVar], 791
imul rcx, qword [qVar]
imul qword [qVar]
所有的格式中, dest运算数都必须是寄存器, 并且所有的运算数都不能为byte. 当使用单个运算数时, imul的格式和mul是一致的. 当使用两个运算数时, 相乘的是src和dest运算数, 并且结果会存放在desc运算数, 覆盖原值. 立即数的尺寸受src运算数的限制, 可以是double word(32bit), 甚至quadword(64bit), 运算结果被裁剪为dest的尺寸后存放在desc. desc不支持8bit的运算数.
代码例子
wNumA dw 1200
wNumB dw 2000
wAns1 dw 0
wAns2 dw 0
dNumA dd 42000
dNumB dd 13000
dAns1 dd 0
dAns2 dd 0
qNumA dq 120000
qNumB dq 230000
qAns1 dq 0
qAns2 dq 0 ; wAns1 = wNumA * 13
mov ax, word [wNumA]
imul ax, 13 ; result in ax
mov word [wAns1], ax ; wAns2 = wNumA * wNumB
mov ax, word [wNumA]
imul ax, word [wNumB] ; result in ax
mov word [wAns2], ax ; dAns1 = dNumA * 113
mov eax, dword [dNumA]
imul eax, 113 ; result in eax
mov dword [dAns1], eax ; dAns2 = dNumA * dNumB
mov eax, dword [dNumA]
imul eax, dword [dNumB] ; result in eax
mov dword [dAns2], eax ; qAns1 = qNumA * 7096
mov rax, qword [qNumA]
imul rax, 7096 ; result in rax
mov qword [qAns1], rax ; qAns2 = qNumA * qNumB
mov rax, qword [qNumA]
imul rax, qword [qNumB] ; result in rax
mov qword [qAns2], rax ; 计算 qAns1 = qNumA * 7096 的另一种方式是:
; qAns1 = qNumA * 7096
mov rcx, qword [qNumA]
imul rbx, rcx, 7096 ; result in rax
mov qword [qAns1], rax
.
整数除法指令 Integer Division
对有符号数和无符号数, 也有不同的除法指令div和idiv. 指令格式
div <src>
div <op8>
div <op16>
div <op32>
div <op64>
div word [wVvar]
div bl
div dword [dVar]
div qword [qVar] idiv <src>
idiv <op8>
idiv <op16>
idiv <op32>
idiv <op64>
idiv word [wVvar]
idiv bl
idiv dword [dVar]
idiv qword [qVar]
因为 dividend / divisor = quotient, 除法要求被除数的尺寸大于除数. 例如要除以8bit除数, 被除数必须为16bit. 和乘法一样, 运算中需要结合使用A和D寄存器, 这也是为了与旧的架构相兼容. 除法中A和D寄存器的组合如下:
Byte Divide: ax for 16-bits
Word Divide: dx:ax for 32-bits
Double-word divide: edx:eax for 64-bits
Quadword Divide: rdx:rax for 128-bits
Byte: al = ax / <src> , rem in ah
Word: ax = dx:ax / <src>, rem in dx
Double: eax = eax / <src>, rem in edx
Quad: rax = rax / <src>, rem in rdx
正确地设置被除数是问题的关键, 对于word, double word, quadword类型的被除数, 都需要用到A和D寄存器. 如果之前刚刚进行过乘法运算, 那么A和D就正好已经被赋值. 否则当前数值就需要升级成较大尺寸并将上半部分放到D寄存器. 对于无符号数, 高地址部分总是全为零, 而对于有符号数, 则需要根据之前的说明对高地址部分进行扩展.出书可以是一个内存地址或寄存器, 但是不能为立即数. 另外, 结果将被放置在A寄存器(al/ax/eax/rax), 余数部分会被放置在ah, dx, edx, 或者rdx 寄存器. 对更大尺寸的被除数的使用与乘法指令一样, 对于简单的除法, 要使用合适的转换保证数值被正确的初始化, 对于无符号数相除, 要将高地址部分置零, 对于有符号数相除, 要根据实际情况置零或置一. 零作为除数参与除法运算将会导致程序崩溃, 要避免零除数.
代码例子
bNumA db 63
bNumB db 17
bNumC db 5
bAns1 db 0
bAns2 db 0
bRem2 db 0
bAns3 db 0
wNumA dw 4321
wNumB dw 1234
wNumC dw 167
wAns1 dw 0
wAns2 dw 0
wRem2 dw 0
wAns3 dw 0
dNumA dd 42000
dNumB dd 3157
dNumC dd 293
dAns1 dd 0
dAns2 dd 0
dRem2 dd 0
dAns3 dd 0
qNumA dq 730000
qNumB dq 13456
qNumC dq 1279
qAns1 dq 0
qAns2 dq 0
qRem2 dq 0
qAns3 dq 0 ; ----
; example byte operations, unsigned ; bAns1 = bNumA / 3 (unsigned)
mov al, byte [bNumA]
mov ah, 0
mov bl, 3
div bl ; al = ax / 3
mov byte [bAns1], al ; bAns2 = bNumA / bNumB (unsigned)
mov ax, 0
mov al, byte [bNumA]
div byte [bNumB] ; al = ax / bNumB
mov byte [bAns2], al
mov byte [bRem2], ah ; ah = ax % bNumB ; bAns3 = (bNumA * bNumC) / bNumB (unsigned)
mov al, byte [bNumA]
mul byte [bNumC] ; result in al
div byte [bNumB] ; al = ax / bNumB
mov byte [bAns3], al ; ----
; example word operations, unsigned ; wAns1 = wNumA / 5 (unsigned)
mov ax, word [wNumA]
mov dx, 0
mov bx, 5
div bx ; ax = dx:ax / 5
mov word [wAns1], ax ; wAns2 = wNumA / wNumB (unsigned)
mov dx, 0
mov ax, word [wNumA]
div word [wNumB] ; ax = dx:ax / wNumB
mov word [wAns2], ax
mov word [wRem2], dx ; wAns3 = (wNumA * wNumC) / wNumB (unsigned)
mov ax, word [wNumA]
mul word [wNumC] ; result in dx:ax
div word [wNumB] ; ax = dx:ax / wNumB
mov word [wAns3], ax ; ----
; example doubleword operations, signed ; dAns1 = dNumA / 7 (signed)
mov eax, dword [dNumA]
cdq ; eax → edx:eax
mov ebx, 7
idiv ebx ; eax = edx:eax / 7
mov dword [dAns1], eax ; dAns2 = dNumA / dNumB (signed)
mov eax, dword [dNumA]
cdq ; eax → edx:eax
idiv dword [dNumB] ; eax = edx:eax/dNumB
mov dword [dAns2], eax
mov dword [dRem2], edx ; edx = edx:eax%dNumB ; dAns3 = (dNumA * dNumC) / dNumB (signed)
mov eax, dword [dNumA]
imul dword [dNumC] ; result in edx:eax
idiv dword [dNumB] ; eax = edx:eax/dNumB
mov dword [dAns3], eax ; ----
; example quadword operations, signed ; qAns1 = qNumA / 9 (signed)
mov rax, qword [qNumA]
cqo ; rax → rdx:rax
mov rbx, 9
idiv rbx ; eax = edx:eax / 9
mov qword [qAns1], rax ; qAns2 = qNumA / qNumB (signed)
mov rax, qword [qNumA]
cqo ; rax → rdx:rax
idiv qword [qNumB] ; rax = rdx:rax/qNumB
mov qword [qAns2], rax
mov qword [qRem2], rdx ; rdx = rdx:rax%qNumB ; qAns3 = (qNumA * qNumC) / qNumB (signed)
mov rax, qword [qNumA]
imul qword [qNumC] ; result in rdx:rax
idiv qword [qNumB] ; rax = rdx:rax/qNumB
mov qword [qAns3], rax
逻辑指令 Logical Instructions
基础逻辑指令
与操作
and <dest>, <src>
and ax, bx
and rcx, rdx
and eax, dword [dNum]
and qword [qNum], rdx 或操作
or <dest>, <src>
or ax, bx
or rcx, rdx
or eax, dword [dNum]
or qword [qNum], rdx 或非操作
xor <dest>, <src>
xor ax, bx
xor rcx, rdx
xor eax, dword [dNum]
xor qword [qNum], rdx 非操作
not <op>
not bx
not rdx
not dword [dNum]
not qword [qNum]
移位操作
逻辑左移, 从右边补零. <imm>和cl 取值必须在1~64之间, <dest>不能是立即数
shl <dest>, <imm>
shl <dest>, cl
shl ax, 8
shl rcx, 32
shl eax, cl
shl qword [qNum], cl
逻辑右移, 从左边补零. <imm>和cl 取值必须在1~64之间, <dest>不能是立即数
shr <dest>, <imm>
shr <dest>, cl
shr ax, 8
shr rcx, 32
shr eax, cl
shr qword [qNum], cl
算术移位将运算数作为一个有符号数进行处理并保留符号. 但是算数移位使用的是四舍五入而标准除法使用的是裁剪, 所以不能用算术移位代替除法指令
算术左移
sal <dest>, <imm>
sal <dest>, cl
sal ax, 8
sal rcx, 32
sal eax, cl
sal qword [qNum], cl
算术右移
sar <dest>, <imm>
sar <dest>, cl
sar ax, 8
sar rcx, 32
sar eax, cl
sar qword [qNum], cl
循环移位指令只是移位方向不同,它们移出的位不仅要进入CF,而且还要填补空出的位
循环左移
rol <dest>, <imm>
rol <dest>, cl
rol ax, 8
rol rcx, 32
rol eax, cl
rol qword [qNum], cl
循环右移
ror <dest>, <imm>
ror <dest>, cl
ror ax, 8
ror rcx, 32
ror eax, cl
ror qword [qNum], cl
控制指令 Control Instructions
.
.
Ubuntu x86-64汇编(4) 数值操作指令的更多相关文章
- Ubuntu x86-64汇编(3) 数值操作指令
指令标注 Operand Notation 指令instruction即运算operation, 操作的对象为一个或多个运算数operand, 使用不同的标记表示不同的约束 <reg> ...
- Ubuntu x86 64 settup nginx rtmp server
常常搭建nginxserver,可是好像每次的情况都不同,这次具体记录这个过程: 平台:unbutu 10.04 内核:2.6.32-33-generic 1, 编译环境搭建. sudo apt-ge ...
- 汇编实现: C库常见函数,串操作指令作用
目录 汇编实现: C库常见函数 一丶汇编实现Strncpy拷贝函数 二丶loads实现Strlen操作. 三丶stos的作用 汇编实现: C库常见函数 一丶汇编实现Strncpy拷贝函数 void _ ...
- 深入理解计算机系统(4.1)---X86的孪生兄弟,Y86指令体系结构
引言 各位猿友们好,计算机系统系列很久没更新了,实在是抱歉之极.新的一年,为了给计算机系统系列添加一些新的元素,LZ将其更改为书的原名<深入理解计算机系统>.这本书非常厚,而且难度较高,L ...
- linux常用操作指令
Linux常用操作指令: 常用指令 ls 显示文件或目录 -l 列出文件详细信息l(list) -a 列出当前目录下所有文件及目录,包括隐藏的a(a ...
- ARM指令集——条件执行、内存操作指令、跳转指令
ARM 汇编指令条件执行 在ARM模式下,任何一条数据处理指令可以选择是否根据操作的结果来更新CPSR寄存器中的ALU状态标志位.在数据处理指令中使用S后缀来实现该功能. 不要在CMP,CMN,TST ...
- 第24篇-虚拟机对象操作指令之getfield
getfield指令表示获取指定类的实例域,并将其值压入栈顶.其格式如下: getstatic indexbyte1 indexbyte2 无符号数indexbyte1和indexbyte2构建为(i ...
- 第25篇-虚拟机对象操作指令之putstatic
之前已经介绍了getstatic与getfield指令的汇编代码执行逻辑,这一篇介绍putstatic指令的执行逻辑,putfield将不再介绍,大家可以自己去研究,相信大家有这个实力. putsta ...
- 深入理解JVM(1)——栈和局部变量操作指令
将常量压入栈的指令 aconst_null 将null对象引用压入栈iconst_m1 将int类型常量-1压入栈iconst_0 将int类型常量0压入栈iconst_1 将int类型常量1压入栈i ...
随机推荐
- BZOJ3328: PYXFIB
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3328 题解:关键在于只处理i%k的项,那么我们就需要用一个式子来表达这个东西. p%k==1. ...
- C C++ 去除 unused的提示
C C++ 去除 unused的提示 #define UNUSED(VAR) {VAR++;VAR--;} unsigned int user_id=0; UNUSED(user_id); 这样就可以 ...
- iOS开发-音乐播放(AVAudioPlayer)
现在的手机的基本上没有人不停音乐的,我们无法想象在一个没有声音的世界里我们会过的怎么样,国内现在的主流的主流网易云音乐,QQ音乐,酷狗,虾米,天天基本上霸占了所有的用户群体,不过并没有妨碍大家对音乐的 ...
- 项目总结——MVC+MongoDB实现文件上传
在做项目的时候我们遇到了视频上传的问题.正式开始项目之前做了一个简单的Demo实现在MVC中视频文件的上 传,考虑到将视频放到MongoDB中上传和读取速度慢的问题,这次我们实现的文件上传是存储的路径 ...
- 文本分类需要CNN?No!fastText完美解决你的需求(后篇)
http://blog.csdn.net/weixin_36604953/article/details/78324834 想必通过前一篇的介绍,各位小主已经对word2vec以及CBOW和Skip- ...
- (转)【Unity Shaders】Vertex Magic —— 访问顶点颜色
转自:http://blog.csdn.net/candycat1992/article/details/38147767 本系列主要参考<Unity Shaders and Effects C ...
- 可以在任何时候attach一个shader到program对象
可以在任何时候attach一个shader到program对象,不一定非要在指定source和编译以后,具体的描述如下: Once you have a program object create ...
- OpenGL ES 3.0之VertexAttributes,Vertex Arrays,and Buffer Objects(九)
顶点数据,也称为顶点属性,指每一个顶点数据.指能被用来描述每个顶点的数据,或能被所有顶点使用的常量值.例如你想绘制一个具有颜色的立方体三角形.你指定一个恒定的值用于三角形的所有三个顶点颜色.但三角形的 ...
- DFS csu1719 Boggle
传送门:id=1719">点击打开链接 题意:真正的题意是,告诉你一些字符串.然后告诉你非常多个字符格子,问这些字符串是否能在字符格子中连起来,在格子中对角线也觉得是连在一起的.假设格 ...
- 用一条sql取得第10到第20条的记录
因为id可能不是连续的,所以不能用取得10<id<20的记录的方法. 有三种方法可以实现:一.搜索前20条记录,指定不包括前10条语句:select top 20 * from tbl w ...