博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Ubuntu x86-64汇编(4) 数值操作指令
阅读量:5736 次
发布时间:2019-06-18

本文共 8229 字,大约阅读时间需要 27 分钟。

整数乘法指令 Integer Multiplication

对于有符号数的乘法有特殊的规则, 因此无符号数乘法和有符号数乘法对应着不同的指令mul和imul. 乘法会产生两倍尺寸的数值结果, 即两个n-bit数相乘会产生2n-bit的数. 两个8bit数相乘会产生16bit的数. 对于乘法指令有许多变种, 例如对于带符号乘法, 一些指令能将结果裁剪至和源数值一样的尺寸.

无符号的乘法 Unsigned Multiplication

通常这种乘法的格式为

mul   
mul
mul
mul
mul
mul word [wVvar]mul almul 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 42bNumB   db 73wAns    dw 0wAns1   dw 0wNumA   dw 4321wNumB   dw 1234dAns2   dd 0dNumA   dd 42000dNumB   dd 73000qAns3   dq 0qNumA   dq 420000qNumB   dq 730000dqAns4  ddq 0; wAns = bNumA^2 or bNumA squaredmov al, byte [bNumA] mul al                  ; result in axmov word [wAns], ax; wAns1 = bNumA * bNumBmov al, byte [bNumA]mul byte [bNumB]        ; result in axmov word [wAns1], ax ; dAns1 = wNumA * wNumBmov ax, word [wNumA]mul word [wNumB]        ; result in dx:axmov word [dAns1], axmov word [dAns1+2], dx; qAns3 = dNumA * dNumBmov eax, dword [dNumA]mul dword [dNumB]       ; result in edx:eaxmov dword [qAns3], eax mov dword [qAns3+4], edx; dqAns4 = qNumA * qNumBmov rax, qword [qNumA]mul qword [qNumB]       ; result in rdx:raxmov qword [dqAns4], raxmov qword [dqAns4+8], rdx

带符号数乘法 Signed Multiplication

带符号数的乘法允许更大范围的运算数和尺寸. 通常的格式为

imul  
imul
,
imul
,
,
imul
imul
imul
imul
imul
,
imul
,
imul
,
imul
,
,
imul
,
,
imul
,
,
imul ax, 17imul alimul ebx, dword [dVar]imul rbx, dword [dVar], 791imul 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 1200wNumB dw ­2000wAns1 dw 0wAns2 dw 0dNumA dd 42000dNumB dd ­13000dAns1 dd 0dAns2 dd 0qNumA dq 120000qNumB dq ­230000qAns1 dq 0qAns2 dq 0; wAns1 = wNumA * ­13mov  ax, word [wNumA]imul ax, ­13           ; result in axmov  word [wAns1], ax; wAns2 = wNumA * wNumBmov  ax, word [wNumA]imul ax, word [wNumB] ; result in axmov  word [wAns2], ax; dAns1 = dNumA * 113mov  eax, dword [dNumA]imul eax, 113         ; result in eaxmov  dword [dAns1], eax; dAns2 = dNumA * dNumBmov  eax, dword [dNumA]imul eax, dword [dNumB]  ; result in eaxmov  dword [dAns2], eax; qAns1 = qNumA * 7096mov  rax, qword [qNumA]imul rax, 7096           ; result in raxmov  qword [qAns1], rax; qAns2 = qNumA * qNumBmov  rax, qword [qNumA]imul rax, qword [qNumB]  ; result in raxmov  qword [qAns2], rax; 计算 qAns1 = qNumA * 7096 的另一种方式是:; qAns1 = qNumA * 7096mov  rcx, qword [qNumA]imul rbx, rcx, 7096      ; result in raxmov  qword [qAns1], rax

.

整数除法指令 Integer Division

对有符号数和无符号数, 也有不同的除法指令div和idiv. 指令格式

div 
div
div
div
div
div word [wVvar]div bldiv dword [dVar]div qword [qVar]idiv
idiv
idiv
idiv
idiv
idiv word [wVvar]idiv blidiv 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 63bNumB db 17bNumC db 5bAns1 db 0bAns2 db 0bRem2 db 0bAns3 db 0wNumA dw 4321wNumB dw 1234wNumC dw 167wAns1 dw 0wAns2 dw 0wRem2 dw 0wAns3 dw 0dNumA dd 42000dNumB dd ­3157dNumC dd ­293dAns1 dd 0dAns2 dd 0dRem2 dd 0dAns3 dd 0qNumA dq 730000qNumB dq ­13456qNumC dq ­1279qAns1 dq 0qAns2 dq 0qRem2 dq 0qAns3 dq 0; ----; example byte operations, unsigned; bAns1 = bNumA / 3 (unsigned)mov  al, byte [bNumA]mov  ah, 0mov  bl, 3div  bl            ; al = ax / 3mov  byte [bAns1], al; bAns2 = bNumA / bNumB (unsigned)mov  ax, 0mov  al, byte [bNumA]div  byte [bNumB]       ; al = ax / bNumBmov  byte [bAns2], almov  byte [bRem2], ah   ; ah = ax % bNumB; bAns3 = (bNumA * bNumC) / bNumB (unsigned)mov  al, byte [bNumA]mul  byte [bNumC]       ; result in aldiv  byte [bNumB]       ; al = ax / bNumBmov  byte [bAns3], al; ----; example word operations, unsigned; wAns1 = wNumA / 5 (unsigned)mov  ax, word [wNumA]mov  dx, 0mov  bx, 5div  bx                 ; ax = dx:ax / 5mov  word [wAns1], ax; wAns2 = wNumA / wNumB (unsigned)mov  dx, 0mov  ax, word [wNumA]div  word [wNumB]       ; ax = dx:ax / wNumBmov  word [wAns2], axmov  word [wRem2], dx; wAns3 = (wNumA * wNumC) / wNumB (unsigned)mov  ax, word [wNumA]mul  word [wNumC]       ; result in dx:axdiv  word [wNumB]       ; ax = dx:ax / wNumBmov  word [wAns3], ax; ----; example double­word operations, signed; dAns1 = dNumA / 7 (signed)mov  eax, dword [dNumA]cdq                     ; eax → edx:eaxmov  ebx, 7idiv ebx                ; eax = edx:eax / 7mov  dword [dAns1], eax; dAns2 = dNumA / dNumB (signed)mov  eax, dword [dNumA]cdq                     ; eax → edx:eaxidiv dword [dNumB]      ; eax = edx:eax/dNumBmov  dword [dAns2], eaxmov  dword [dRem2], edx ; edx = edx:eax%dNumB; dAns3 = (dNumA * dNumC) / dNumB (signed)mov  eax, dword [dNumA]imul dword [dNumC]      ; result in edx:eaxidiv dword [dNumB]      ; eax = edx:eax/dNumBmov  dword [dAns3], eax; ----; example quadword operations, signed; qAns1 = qNumA / 9 (signed)mov  rax, qword [qNumA]cqo                     ; rax → rdx:raxmov  rbx, 9idiv rbx                ; eax = edx:eax / 9mov  qword [qAns1], rax; qAns2 = qNumA / qNumB (signed)mov  rax, qword [qNumA]cqo                     ; rax → rdx:raxidiv qword [qNumB]      ; rax = rdx:rax/qNumBmov  qword [qAns2], raxmov  qword [qRem2], rdx ; rdx = rdx:rax%qNumB; qAns3 = (qNumA * qNumC) / qNumB (signed)mov  rax, qword [qNumA]imul qword [qNumC]      ; result in rdx:raxidiv qword [qNumB]      ; rax = rdx:rax/qNumBmov  qword [qAns3], rax

 

逻辑指令 Logical Instructions

基础逻辑指令

与操作and   
,
and ax, bxand rcx, rdxand eax, dword [dNum]and qword [qNum], rdx或操作or
,
or ax, bxor rcx, rdxor eax, dword [dNum]or qword [qNum], rdx或非操作xor
,
xor ax, bxxor rcx, rdxxor eax, dword [dNum]xor qword [qNum], rdx非操作not
not bxnot rdxnot dword [dNum]not qword [qNum]

移位操作

逻辑左移, 从右边补零. <imm>和cl 取值必须在1~64之间, <dest>不能是立即数

shl   
,
shl
, clshl ax, 8shl rcx, 32shl eax, clshl qword [qNum], cl

逻辑右移, 从左边补零. <imm>和cl 取值必须在1~64之间, <dest>不能是立即数

shr   
,
shr
, clshr ax, 8shr rcx, 32shr eax, clshr qword [qNum], cl

算术移位将运算数作为一个有符号数进行处理并保留符号. 但是算数移位使用的是四舍五入而标准除法使用的是裁剪, 所以不能用算术移位代替除法指令

算术左移

sal   
,
sal
, clsal ax, 8sal rcx, 32sal eax, clsal qword [qNum], cl

算术右移

sar   
,
sar
, clsar ax, 8sar rcx, 32sar eax, clsar qword [qNum], cl

循环移位指令只是移位方向不同,它们移出的位不仅要进入CF,而且还要填补空出的位

循环左移

rol   
,
rol
, clrol ax, 8rol rcx, 32rol eax, clrol qword [qNum], cl

循环右移

ror   
,
ror
, clror ax, 8ror rcx, 32ror eax, clror qword [qNum], cl

控制指令 Control Instructions

 

.

 

.

转载地址:http://ydgwx.baihongyu.com/

你可能感兴趣的文章
Aho-Corasick automation-KMP
查看>>
【http】post和get请求的区别
查看>>
/etc/profile
查看>>
TFS强制撤销某个工作区的文件签出记录
查看>>
编写who命令
查看>>
2.1 sikuli 中编程运行
查看>>
愚公移山第一章伪代码
查看>>
常见的位运算技巧总结(膜wys)
查看>>
python魔法函数(二)之__getitem__、__len__、__iter__
查看>>
EL表达式无法显示Model中的数据
查看>>
Linux应用小技巧
查看>>
考题纠错2
查看>>
ps6-工具的基础使用
查看>>
关于CefSharp.WinForms的学习
查看>>
灵活运用 SQL SERVER FOR XML PATH
查看>>
es 加磁盘扩容
查看>>
linux 参数内核
查看>>
使用Azcopy在Azure上进行HBase的冷热备份还原
查看>>
计组_定点数一位乘_布斯公式
查看>>
linux下使用过的命令总结(未整理完)
查看>>