x86汇编语言的MOV指令

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了x86汇编语言的MOV指令相关的知识,希望对你有一定的参考价值。

最近在看ucos操作系统,有一个移植到x86的例程,从上面看到有两句关于x86的汇编指令,没看懂啥意思,
MOV ebx ,[OSTCBCur]
MOV [ebx],esp

其中OSTCBCur 是C语言中的指向一个结构体类型的指针变量。

请高手来帮我解答,最好一句一句解答,告诉我[OSTCBCur]是什么?[ebx]是什么?加了个中括号感觉很晕。先谢谢了!!

MOV在汇编语言中是 数据传送指令。

用法如下:

mov — Move (Opcodes: 88, 89, 8A, 8B, 8C, 8E, ...)

mov指令将第二个操作数(可以是寄存器的内容、内存中的内容或值)复制到第一个操作数(寄存器或内存)。mov不能用于直接从内存复制到内存,其语法如下所示:

mov <reg>,<reg>
mov <reg>,<mem>
mov <mem>,<reg>
mov <reg>,<const>
mov <mem>,<const>

Examples
mov eax, ebx — 将ebx的值拷贝到eax
mov byte ptr [var], 5 — 将5保存找var指示内存中的一个字节中

参考技术A 1、第一句是将C语言中的指向一个结构体类型的指针变量传送到ebx寄存器中(ebx是CPU中的32位寄存器)
2、第二句是将esp堆栈寄存器(32位)的内容传送到以ebx寄存器为地址的单元里。
即将edp堆栈寄存器的内容传送到C语言中的指向一个结构体类型的指针变量中。本回答被提问者采纳
参考技术B 加中括弧是间接寻址,把ostcbcur这个指针里的地址指向的内容放到ebx中,esp是堆栈指针寄存器追问

你确定是[OSTCBCur]的结果是内容不是地址?

追答

所以是二次寻址

追问

我觉得你说的不对,能不能再好好想想再回答我,如果按你的解释,再通过上下文,一点都解释不通。

我觉得[OSTCBCur]应该是OSTCBCur这个指针变量存储的内容也就是结构体地址。这样两句都能解释通了。

汇编学习笔记-80x86寻址方式

寻址方式

  所谓寻址方式就是表示指令中数据所在地址的方式。一共有七种寻址方案

    立即数寻址

    寄存器寻址

    直接寻址

    寄存器间接寻址

    寄存器相对选址

    基址变质寻址

    相对基址变质寻址

 

      在此之前,先介绍一个数据复制指令 MOV 指令, 格式是 MOV AX, BX 。 AXBX是寄存器上一章介绍过的MOV就是指令。 指令的含义就是将BX的值复制给AX。C语言的表述就是AX=BX;

  举个例子 如果一开始 AX=5; BX=0;

  MOV AX,BX 之后 AX = BX 都是0;

 

立即数寻址 / 寄存器寻址

  MOV AX, 1  ; AX = 1

  立即数寻址,我觉得称不上寻址,因为他给出的不是地址,而就是实际的数字,上面的命令中 1 就是立即数,而AX就是寄存器寻址所以寄存器寻址就是直接使用寄存器,数据直接存入指定的寄存器

  寄存器寻址可以使用的寄存器是AX(AL AH) BX(BL BH) CX(CL CH) DX(DL DH) SI DI SP BP等, 这些寄存器可以任意组合,举例如下

  MOV AX, BX  ; AX = BX

  MOV BX, AX  ; BX =AX

  MOV SI, DI  ; SI = DI

  MOV DI, SI  ; DI = SI

  这两种寻址方式是不涉及内存的操作的,所以速度是最快的,所以为了性能考虑应该尽量多的使用这两种寻址方式的操作。

  注意: MOV 1, AX 是非法的,应为1就是常数,你不能给常数赋值

 

直接寻址

  MOV AX, [1234H]

  MOV AX, ES:[1234H]

  直接寻址就是直接给出内存地址的寻址方式,格式是 段寄存器:[偏移地址] 偏移地址是立即数,用[]括起来。当然也可以直接省去前面的段寄存器写作 [偏移地址],这样汇编会自动选择一个默认的段地址,一般来说是DS段寄存器前面讲过内存地址是 段地址X16+偏移地址,所以使用段寄存器:[偏移地址] 给出的地址就是 段寄存器的值X16 + 偏移地址,

  举例

  MOV AX, DS:[1234H]

  这句话的就是将DSx16+1234H处的数据复制给AX寄存器,假设DS=5000H 那么就是将内存51234处的数据复制给AX,具体是多少就要看当时内存中是什么数据了。

  MOV AX, ES:[1234H]

  就是显示指定了使用的ES段寄存器,所以就是将ESx16+1234H处的数据复制给AX

  注意   ":"前面只能跟着段寄存器 DS ES SS CS寄存器

  这一条寻址方式其实是最基础的寻址方式,接下来的其他几种寻址方式都是只是[]偏移地址的表示方式发生了一些变化而已。

 

寄存器间接寻址

  MOV AX, [BX]

  MOV AX,CS:[BX]

  本质上和直接寻址是没太大区别的,唯一的区别就是在直接寻之中[]中的数据是直接给出的,但是在寄存器间接寻址中这个数字是存储在寄存器中而已。

  这里有个限制就是[] 中能使用的寄存器只有 BX BP SI DI ,如果使用的是BX SI DI则默认的段寄存器是DS,如果是BP寄存器则默认使用SS寄存器。

  当然如果特意指定寄存器那么就用指定的寄存器。

  举例 AX =1 BX = 1111H DS = 5000H

  MOV AX, [BX] ; 等于MOV AX,DS:[1111H] 就是将51111H内存出的数据复制到AX

 

寄存器间接寻址

  MOV AX, [BX + 1111H]

  在寄存器间接寻址的基础上加上立即数其他规则还是和寄存器间接寻址一样的

  举例 AX =1 BX = 2222H DS=5000H

  MOV AX, [BX + 1111H] ; 等于 MOV AX, DS:[2222H + 1111H] => MOV AX, DS:[3333H]

 

基址变址寻址

  MOV AX,[BX+SI]

  基址变址寻址就是用了两个寄存器 {BX/BP}+{SI/DI}, 如果是出现BP寄存器则默认使用SS寄存器,否则默认使用DS寄存器.规则和寄存器间接寻址也是一样的。

  要注意的是这里分为两组了寄存器 BX/BPSI/DI,一组中只能出现一个,即不能出现[ BX+BP ][SI+DI],从名字中就可以看出的 基址+变址,

    BX 基地址寄存器

    BP 基址指针寄存器(Base Point)  

    SI 源地址寄存器(Source Index)

    DI 目的地址寄存器(Destination Index)

  举例 AX =1 BX=1111H SI=2222H DS= 5000H

  MOV AX,[BX+SI]; 等于 MOV AX, DS:[BX+SI] => MOV AX, DS:[1111H+2222H] => MOV AX, DS:[3333H]

 

相对基址变址寻址

   MOV AX,[BX+SI+4444H]

   可以看出就是在基址变址寻址的基础上加上了立即数其他规则不变

 举例 AX =1 BX=1111H SI=2222H DS= 5000H

  MOV AX,[BX+SI+4444H]; 等于 MOV AX, DS:[BX+SI+4444H] => MOV AX, DS:[1111H+2222H+4444H] => MOV AX, DS:[7777H]

 

总结:

  在我看来其实就三种寻址方式

  1. 立即数寻址 MOV AX, 1    直接给出数据

  2. 寄存器寻址 MOV AX, BX    地址是寄存器

  3. 内存寻址  MOV AX, 段寄存器 : [地址]  

  地址使用 [] 括起来,[] 中的结果就是数据在内存中的偏移地址,[] 可以使用两组寄存器 (BX/BPSI/DI) 和 立即数的任意组合,同组寄存器不能同时出现,段寄存器如果不指定则如果出现了BP寄存器就默认使用SS段寄存器否则默认使用DS寄存器

    寄存器间接寻址  = [ 只用一个寄存器]

    寄存器相对选址 = [用一个寄存器+立即数]

    基址变质寻址 = [用两个寄存器]

    相对基址变质寻址 = [用两个寄存器+立即数]

    写个公式就是 [地址] = [  {BX | BP | 空} + {SI | DI | 空} + {立即数 | 空}  ]

  其实这些寻址方式在使用汇编写代码的时候都是有对应的使用场景的,这个在以后会介绍的。 

以上是关于x86汇编语言的MOV指令的主要内容,如果未能解决你的问题,请参考以下文章

X86中mov和movl指令的区别?我在阅读汇编时遇到了一些麻烦[重复]

Android 逆向x86 汇编 ( call 子函数调用指令 | jmp 跳转指令 | lea 加载指令 | mov 数据传送指令 )

Android 逆向x86 汇编 ( call 子函数调用指令 | jmp 跳转指令 | lea 加载指令 | mov 数据传送指令 )

什么时候应该在 x86 汇编中使用 MOVS 而不是 MOV?

x86汇编指令集

arm汇编 ldr r0 =0x00000000 这个=号代表啥啊