这个指令当中,因为没有立即数,因此FF后面的字节就是0x14,而 [ecx+4*eax] 就需要用SIB字节来表示。 imm(立即数) imm8 - 立即数字节。imm8 符号是 -128 到 +127(含)之间的一个有符号数字。 对于结合使用 imm8 与字或双字操作数的指令,立即数会进行符号扩展,以形成一个字或双字。字的高位字节使用立即数的最高位填充。 imm16 - 操作数大小属性等于 16 位的指令使用的立即数字。 128 位 XMM 寄存器有:XMM0 到 XMM7。 xmm/m32 - XMM 寄存器,或是 32 位内存操作数。128 位 XMM 寄存器有:XMM0 到 XMM7。 xmm/m128 - XMM 寄存器,或是 128 位内存操作数。128 位 XMM 寄存器有:XMM0 到 XMM7。内存的内容位于有效地址计算提供的地址。 参考 CALL指令有多少种写法
操作数被分为三种 立即数 表示常数值,立即数的书写方法是 $ 后面跟一个标准C表示法表示的整数 寄存器 表示整个寄存器的内容,将寄存器集合看成数组 R ,用寄存器标识符作为索引 用 r_a 表示任意寄存器 内存引用 会根据计算出来的地址 (有效地址) 访问某个内存位置 有多种不同的 寻址模式 ,允许不同形式的内存引用 表格底部表示的是最常用的形: 立即数偏移 Imm 基址寄存器 r_b 必须是64位寄存器 注:常规的 movq 指令只能以表示为32位补码数字的立即数作为源操作数 而 movabsq 指令能够以任意64位立即数值作为源操作数,且只能以寄存器为目的 源操作数(source) 指定的值是一个立即数 移位量可以是一个立即数,或放在单字节寄存器 %cl 中 注:这些指令只允许以这个特定的寄存器作为操作数 在x86-64中,移位操作对 w 位长的数据值进行操作,位移量是由 %cl 寄存器的低 m 位决定的 立即数 作为操作数 浮点比较操作 以上指令类似于CMP指令 参数S2必须在 XMM 寄存器中,而 S1 可以在 XMM 寄存器中,也可以在内存中 浮点比较指令会设置三个条件码: 零标志位 ZF 进位标志位
领8888元新春采购礼包,抢爆款2核2G云服务器95元/年起,个人开发者加享折上折
SSE(Streaming SIMD Extension)拥有16个128位的寄存器,也就是之前接触过的xmm0到xmm15,还有一个控制寄存器mxcsr。 或xmm1寄存器。 addps(add packed single precision): 将两个xmm寄存器的值按照单精度划分并相加。 movss(move scalar single precision)将内存数据拷贝到xmm寄存器。 , 10, 12 Reverse of Sum Vector: 12, 10, 8, 6 SSE中也有操作字符串比较的指令: image.png image.png 指令的第三个参数imm8是一个立即数
,ESP栈顶寄存器,EBP栈底寄存器(基址),这两个寄存器就像是好基友,两个寄存器相互配合,来让堆栈有条不乱. ,qword ptr ds:[<__real@40247d70a3d70a3d>] | 将10.245放入XMM0寄存器 00411470 | F2:0F110424 | movsd &number1); printf("您输入的数字: %d\n", number1); number2 = 100; return 0; } 如下反汇编代码可以看出,全局变量的访问是直接通过立即数 push consoleapplication1.415858访问的,此立即数是通过编译器编译时就写入到了程序中的,所以也就可以直接进行访问了. 004113E0 | 68 00804100 main.c:12 探索局部变量的奥秘: 局部变量的访问是通过栈指针相对间接访问,也就是说局部变量是程序动态创建的,通常是调用某个函数或过程时动态生成的,局部变量作用域也仅限于函数内部,且其地址也是一个未知数,
移位指令 移位指令对操作数按某种方式左移或右移,移位位数可以由立即数直接给出,或由CL间接给出。移位指令分一般移位指令和循环移位指令。 1 一般移位指令 (1) 算术/逻辑左移指令。 格式:SAR DEST,OPRD 功能:按照操作数OPRD规定的移位次数,对目的操作数进行右移操作,最低位移至CF中,最高位(即符号位)保持不变。如图3 12(b)所示。 格式:SHR DEST,SRC 功能:按照操作数OPRD规定的移位位数,对目的操作数进行右移操作,最低位移至CF中。每移动一位,左边补一位0。 算术右移只要无溢出,每右移一次相当于原数除以2。 目的操作数可以是16位或32位通用寄存器或存储器操作数。源操作数SRC允许为16位或32位通用寄存器。操作数OPRD可以为立即数或 CL。目的操作数和源操作数SRC数据类型必须一致。
入门 在C中嵌入汇编的最大问题是如何将C语言变量与指令操作数相关联。当然,gcc都帮我们想好了。下面是是一个简单例子。 这样gcc就知道如何将这条嵌入式汇编语句转成实际的汇编指令了: fsinx:汇编指令名 %1, %0:汇编指令操作数 “=f”(result):操作数%0是一个浮点寄存器,与变量result关联(对输出操作数 常用的constraints有以下几个(更多细节参见gcc手册): m 内存操作数 r 寄存器操作数 i 立即数操作数(整数) f 浮点寄存器操作数 F 立即数操作数(浮点) 指定寄存器 有时候我们需要在指令中使用指定的寄存器;典型的栗子是系统调用,必须将系统调用码和参数放在指定寄存器中。 以指定寄存器语法声明的变量,所占用的寄存器也不能和隐含改变规则有交叉。这个应该好理解:隐含改变规则是告诉gcc有额外的寄存器需要照顾,自然不能和输入/输出寄存器有交集。
( :光标移至句首 }:光标移至段落开头 {:光标移至段落结尾 nG:光标移至第n行首 n+:光标下移n行 n-:光标上移n行 n$:光标移至第n行尾 H :光标移至屏幕顶行 M : 光标移至屏幕中间行 L :光标移至屏幕最后行 0:(注意是数字零)光标移至当前行首 $:光标移至当前行尾 屏幕翻滚类命令 Ctrl+u:向文件首翻半屏 Ctrl+d:向文件尾翻半屏 Ctrl command:将命令command的输出结果放到当前行 寄存器操作 “?nyy:将当前行及其下n行的内容保存到寄存器?中,其中?为一个字母,n为一个数字 “? nyw:将当前行及其下n个字保存到寄存器?中,其中?为一个字母,n为一个数字 “?nyl:将当前行及其下n个字符保存到寄存器?中,其中?为一个字母,n为一个数字 “?p:取出寄存器? n为行数,该命令立即使光标跳到指定行。 Ctrl+G——光标所在位置的行数和列数报告。 w、b——使光标向前或向后跳过一个单词。
在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可 例如指令movl允许寄存器到寄存器,立即数到寄存器等,但是不允许内存到内存的操作,因此两个操作数不能同时使用"m"作为限定字符。 因此上面的汇编语句代码与下面的伪代码等价:btsl nr, ADDR,该指令的两个操作数不能全是内存变量,因此将nr的限定字符串指定为"Ir",将nr 与立即数或者寄存器相关联,这样两个操作数中只有ADDR 0-63之间的立即数(用于64位移位指令) "N" 0-255之间的立即数(用于out指令) "i" 立即数 "n" 立即数,有些系统不支持除字以外的立即数,
( :光标移至句首 }:光标移至段落开头 {:光标移至段落结尾 nG:光标移至第n行首 n+:光标下移n行 n-:光标上移n行 n:光标移至第n行尾 H :光标移至屏幕顶行 M :光标移至屏幕中间行 L :光标移至屏幕最后行 0:(注意是数字零)光标移至当前行首 :光标移至当前行尾 屏幕翻滚类命令 Ctrl+u:向文件首翻半屏 Ctrl+d:向文件尾翻半屏 Ctrl+f:向文件尾翻一屏 Ctrl command:将命令command的输出结果放到当前行 寄存器操作 “?nyy:将当前行及其下n行的内容保存到寄存器?中,其中?为一个字母,n为一个数字 “? nyw:将当前行及其下n个字保存到寄存器?中,其中?为一个字母,n为一个数字 “?nyl:将当前行及其下n个字符保存到寄存器?中,其中?为一个字母,n为一个数字 “?p:取出寄存器? n为行数,该命令立即使光标跳到指定行。 Ctrl+G——光标所在位置的行数和列数报告。 w、b——使光标向前或向后跳过一个单词。
立即数使用美元符号标记,比如56。但是立即数的使用是有限制范围的。 寄存器 使用寄存器寻址,比如%rbx。 间接引用 通过寄存器中包含的地址进行寻址,比如(%rsp),表示引用%rsp指向的那个值。 但是,对于一个编译器项目,使用MOV指令搬运寄存器之间或者寄存器与立即数之间的值,然后仅使用寄存器操作,会更加方便。 前8个浮点型参数依次存储在寄存器%xmm0-%xmm7。 超过这些寄存器个数的参数才被压栈。 如果函数接受可变数量的参数(如printf),则必须将%rax寄存器设置为浮动参数的数量。 MOV拷贝寄存器之间的数据和常量,而LDR和STR指令拷贝寄存器和内存之间的数据。 MOV指令可以把一个立即数或者寄存器值搬运到另一个寄存器中。ARM中,用#表示立即数,这些立即数必须小于等于16位。 如果比较一个寄存器值和立即数,立即数必须作为第二个操作数: CMP Rd, Rn CMP Rd, #imm 另外,也可以在算术指令后面添加S标志,以相似的方式更新CPSR寄存器的相应标志位。
( :光标移至句首 }:光标移至段落开头 {:光标移至段落结尾 nG:光标移至第n行首 n+:光标下移n行 n-:光标上移n行 n:光标移至第n行尾 H :光标移至屏幕顶行 M :光标移至屏幕中间行 L :光标移至屏幕最后行 0:(注意是数字零)光标移至当前行首 :光标移至当前行尾 屏幕翻滚类命令 Ctrl+u:向文件首翻半屏 Ctrl+d:向文件尾翻半屏 Ctrl+f:向文件尾翻一屏 command:将命令command的输出结果放到当前行 寄存器操作 “?nyy:将当前行及其下n行的内容保存到寄存器?中,其中?为一个字母,n为一个数字 “? nyw:将当前行及其下n个字保存到寄存器?中,其中?为一个字母,n为一个数字 “?nyl:将当前行及其下n个字符保存到寄存器?中,其中?为一个字母,n为一个数字 “?p:取出寄存器? n为行数,该命令立即使光标跳到指定行。 Ctrl+G——光标所在位置的行数和列数报告。 w、b——使光标向前或向后跳过一个单词。
例: INTEL AT&T MOV EAX,EBX movl %ebx,%eax 1.3 指令前缀 在INTEL语法中寄存器和立即数不需要前缀; AT&T中寄存器需要加前缀“%”;立即数需要加前缀 2.2 内嵌汇编举例在内嵌汇编中,可以将C 语言表达式指定为汇编指令的操作数,而且不用去管如何将C 语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可 g” 将输入变量放入eax,ebx,ecx ,edx中的一个或者作为内存变量 “X”操作数可以是任何类型 立即数 “I” 0-31 之间的立即数(用于32位移位指令) “J” 0-63 之间的立即数 (用于64 位移位指令) “N” 0-255 ,之间的立即数(用于out 指令) “i” 立即数 “n” 立即数,有些系统不支持除字以外的立即数,这些系统应该使用“n”而不是“i” 匹配 “0”, =”);"Ir" (nr)表示nr,为 0-31之间的立即数(“I”)或者一个寄存器操作数(“r”)。
因此,称32位数为“双字( double words)”,称64位数为“四字( quad words)。下表给出了C语言基本数据类型对应的x86-64表示。 本文链接:https://blog.csdn.net/qq_16933601/article/details/109602212 三种类型的操作数 1.立即数,用来表示常数值,比如,$0x1f 不同的指令允许的立即数值范围不同,汇编器会自动选择最紧凑的方式进行数值编码。 括号中是一种比例变址寻址,将第一个数加上第二个数和第三个数的乘积作为地址寻址,leal的效果使源操作数正好是寻址得到的地址,然后将其赋值给%eax寄存器。 汇编代码用寄存器的 SSE XMM寄存器名字%xmm0~%xmm15来引用它们,每个XMM寄存器都是对应的YMM寄存器的低128位(16字节)。 ?
; ·目的操作数不允许为CS和立即数; ·当源操作数为立即数时,目的操作数不允许为段寄存器; ·传送操作不影响标志位。 源操作数可以是通用寄存器、存储器或立即数。目的操作数可以是通用寄存器或存储器操作数。 源操作数可以是通用寄存器、存储器或立即数。目的操作数可以是通用寄存器或存储器操作数。 源操作数可以是通用寄存器、存储器或立即数。目的操作数可以是通用寄存器或存储器操作数。 源操作数可以为通用寄存器、存储器或立即数。目的操作数可以为通用寄存器或存储器操作数。
其中OPR用除立即数外的任何寻址方式。 在其他机型中可使用CL和CNT,且CNT的值除可用1外,还可以用8位立即数指定范围从1到31的移位次数。有关OPR和CNT的规定适用于以下所有指令操作。具体格式如下所述。以逻辑右移为例。 在移位中,作为源操作数的寄存器提供移位值,以补目的操作数因移位引起的空缺,而指令执行完成后,只取目的操作数作为移位的结果,源操作数寄存器则保持指令执行前的值不变。 这是一组三操作数指令,其中DST可以用除立即数以外的任一种寻址方式指定字或双字操作数。源操作数则只能使用寄存器方式指定与目的操作数想同长度的字或双字。 第三个操作数CNT用来指定移位次数,它可以是一个8位的立即数,也可以是CL,用其内容存放移位计数值。移位计数值的范围为1到31,对于大于31的数,机器则自动取模32的值来取代。
; 串操作的目标操作数所用的段寄存器和偏移量一定是ES和DI; 操作数的寻址方式 1.立即寻址方式:MOV AH,80H ADD AX,1234H 2.寄存器寻址方式 :MOV 进制伪指令RADIX .RADIX exp 伪指令前面要用点开始,exp的值必须是[2,16]内的一个整数 .radix 8 B1 DB 10,11,12 这三个数是八进制 等价语句 符号名 数据传送指令 传送指令MOV 格式如下:MOV Reg/Mem,Reg/Mem/Imm 寄存器Reg 存储器Mem 立即数Imm ---- 注意:①两个操作数的数据类型要相同,要同为8位、16位 ②两个操作数不能同时为段寄存器, ③代码段寄存器CS不能为目的操作数,但可作为源操作数 ④立即数不能直接传给段寄存器 ⑤立即数不能作为目的操作数 ⑥指令指针IP,不能作为MOV指令的操作数 ⑦ 但又不希望改变操作数,即使用于检查一个字节或字中的某些特定位是否有一位为1 移位指令 1.SHL指令(逻辑左移) 相当于将数倍增 2.SHR指令(逻辑右移) 将一个无符号数向右移动,左边出现空位补0,右边低位移至
OPRD2为立即数,也可以是任意一个通用寄存器操作数.立即数只能用于源操作数. OPRD1和OPRD2均为寄存器是允许的,一个为寄存器而另一个为存储器也是允许的,但不允许两个都是存储器操作数. OPRD2为立即数,也可以是任意一个通用寄存器操作数.立即数只能用于源操作数. OPRD1和OPRD2均为寄存器是允许的,一个为寄存器而另一个为存储器也是允许的, 但不允许两个都是存储器操作数. 说明: 目的操作数OPRD1为任一通用寄存器或存储器操作数.源操作数OPRD2为立即数,任一通用寄存器或存储器操作数. OPRD2为任意通用寄存器或存储器操作数,立即数也可用作源操作数OPRD2. 说明: OPRD1 为目的操作数,可以是寄存器、存储器、累加器. OPRD2 为源操作数,可以是寄存器、存储器、累加器和立即数.
虚拟机 eBPF 是一个 RISC 寄存器机,共有 11 个 64 位寄存器[1],一个程序计数器和一个 512 字节固定大小的堆栈。 操作码编码指令类 BPF_JMP 、操作(通过 BPF_OP 位域传递以确保正确性)和表示它是对立即数/常量值 BPF_K 的操作的标志进行编码。 #define BPF_OP(code) ((code) & 0xf0) #define BPF_K 0x00 /* 针对立即数的条件跳转,if (dst_reg 'op' imm32) goto pc BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ 将堆栈地址指针移至 KubeSphere 已被 Aqara 智能家居、杭州数跑科技、本来生活、新浪、华夏银行、四川航空、国药集团、微众银行、紫金保险、中通、中国人保寿险、中国太平保险、中移金科、Radore、ZaloPay
;在源操作数是立即数时,目标操作数不能是段寄存器;IP和CS不作为目标操作数,FLAGS一般也不作为操作数在指令中出现。 堆栈操作指令 先进后出,以字为单位 压栈:PUSH OPRD 16位寄存器或存储器两单元 出栈:POP OPRD 指令的操作数必须是16位;操作数可以是寄存器或存储器两单元,但不能是立即数;不能从栈顶弹出一个字给 AL不变(即将AL的符号位移至AH) CBW属符号扩展指令,它可以把8位扩展到16位,扩展前后两数的真值不变,主要用于数据类型不同时用符号扩展指令可以使得数据类型相同。 NEG OPRD 操作:0-OPRD-->OPRD 乘法指令 乘法指令采用隐含寻址,隐含的是存放被乘数的累加器AL或AX及存放结果的AX,DX; 1.无符号的乘法指令MUL MUL OPRD不能是立即数和段寄存器 控制二进制位向左或向右移动的指令 非循环移位指令 循环移位指令 移动移动1位时由指令直接给出;移动两位及以上时,移位次数必须由CL指定 1.非循环移位指令 逻辑左移SHL 格式: SHL OPR,CNT 注: OPR不能是立即数和段寄存器操作数
程序本身:只读的程序数据片段,比如int i=4,这个4存储于程序本身,在汇编里面又叫立即数(immediate number)。 知道了数据的存储地方,那么数据的传递就分为以下四个方面: 从内存到寄存器; 从寄存器到内存; 从立即数到寄存器; 从立即数到内存。 而AT&T格式是通过指令的后缀来说明,同样的指令为movl $4, -4(%rbp);并且存储的地方,AT&T汇编是通过前缀来区别,比如%q前缀表示寄存器,$表示立即数,()表示内存。 函数的逻辑从第三条语句真正开始: mov DWORD PTR [rbp-4],edi表示将寄存器edi中的4个字节的值(DWORD PTR)移至 [rbp-4] 对应内存地址中。 随后,使用cmp指令将内存中的数和立即数6进行比较(即,j>6),此指令会改变标志寄存器%eflags的状态。
扫码关注腾讯云开发者
领取腾讯云代金券