我想问一下CMPXCHG在8位内存字段上使用指令是否比在32位字段上使用指令更糟糕。
我正在使用C11 stdatomic.h来实现一些同步方法。
我正在查看汇编中的不同指令,我对如何决定不同操作数和操作码的长度感到困惑.
这是你应该从经验中得知的东西,还是有办法找出哪个操作数/运算符组合占用了多少字节?
例如:
push %ebp ; takes up one byte
mov %esp, %ebp ; takes up two bytes
Run Code Online (Sandbox Code Playgroud)
所以问题是:
在看到给定的指令后,如何推断出其操作码需要多少字节?
我一直在尝试在我的 Linux 操作系统上学习 32 位 Intel x86 nasm 语法程序集,我遇到了一个关于四个通用 32 位寄存器的问题。
从我一直思考,EAX是,本来要使用的32位寄存器与16位寄存器AX,其中又分为啊(高8位)和人(低8位)。ebx、ecx 和 edx 也是如此。
然而,在阅读了一篇快速文章后,我变得有点困惑。
32 位寄存器是否由 16 位寄存器(依次由两个 8 位寄存器组成)加上额外的 16 位组成?
到目前为止,我在谷歌上读到的所有结果都说明了它们的用途,而不是它们的实际组成。
我开始学习汇编程序,这对我来说并不合乎逻辑.
为什么我不能在寄存器中使用多个更高的字节?
我理解rax- > eax- > 的历史原因ax,所以让我们关注新的 64位寄存器.例如,我可以使用r8和r8d,但为什么不r8dl和r8dh?同样适用于r8w和r8b.
我最初的想法是,我可以使用8个r8b在同一时间寄存器(就像我可以做的al,并ah在同一时间).但我不能.并且使用r8b使完整的r8寄存器"忙".
这提出了一个问题 - 为什么?如果您不能同时使用其他部件,为什么还只需要使用寄存器的一部分?为什么不保持只r8忘记下部?
我可以使用MOV指令将存储在内存中的数据项移动到我选择的通用寄存器中.
MOV r8, [m8]
MOV r16, [m16]
MOV r32, [m32]
MOV r64, [m64]
Run Code Online (Sandbox Code Playgroud)
现在,不要拍我,但怎么是下面的实现:MOV r24, [m24]?(我很欣赏后者不合法).
在我的例子中,我想移动字符"Pip",即0x706950h,以注册rax.
section .data ; Section containing initialized data
14 DogsName: db "PippaChips"
15 DogsNameLen: equ $-DogsName
Run Code Online (Sandbox Code Playgroud)
我首先认为我可以分别移动字节,即首先是一个字节,然后是一个字,或者是它们的某种组合.但是,我不能引用的"顶半" eax,rax,所以这倒下的第一个障碍,因为我最终会在写入任何数据首先被感动.
我的解决方案
26 mov al, byte [DogsName + 2] ; move the character “p” to register al
27 shl rax, 16 ; shift bits left by 16, clearing ax to receive characters “pi”
28 mov ax, word [DogsName] …Run Code Online (Sandbox Code Playgroud) 我正在学习MOV汇编中的数据移动()。
我尝试编译一些代码以查看 x86_64 Ubuntu 18.04 机器中的程序集:
typedef unsigned char src_t;
typedef xxx dst_t;
dst_t cast(src_t *sp, dst_t *dp) {
*dp = (dst_t)*sp;
return *dp;
}
Run Code Online (Sandbox Code Playgroud)
哪里。src_t unsigned char至于,dst_t我试过了char,,short和int。long结果如下所示:
// typedef unsigned char src_t;
// typedef char dst_t;
// movzbl (%rdi), %eax
// movb %al, (%rsi)
// typedef unsigned char src_t;
// typedef short dst_t;
// movzbl (%rdi), %eax
// movw %ax, (%rsi)
// typedef unsigned …Run Code Online (Sandbox Code Playgroud) 我注意到条件移动指令的可扩展性比普通的mov. 例如,它不支持立即数,也不支持寄存器的低字节。
出于好奇,为什么该Cmov命令比一般mov命令的限制性要大得多?例如,为什么两者不允许这样的事情:
mov $2, %rbx # allowed
cmovcc $1, %rbx # I suppose setcc %bl could be used for the '1' immediate case
Run Code Online (Sandbox Code Playgroud)
附带说明一下,我注意到在使用 Compiler Explorer 时, 的使用量比和cmovcc少得多。通常是这种情况吗?如果是,为什么它的使用频率低于其他条件句?jmpccsetcc
我有一个内存位置,其中包含一个我想要与另一个角色进行比较的角色(并且它不在堆栈的顶部,所以我不能只是pop它).如何引用内存位置的内容以便进行比较?
基本上我如何在语法上做到这一点.
这是复制(转换)未签名寄存器的指令:http : //www.felixcloutier.com/x86/MOVZX.html
基本上,该指令具有8-> 16、8-> 32、8-> 64、16-> 32和16-> 64。
32-> 64转换在哪里?我需要为此使用签名版本吗?
如果是这样,如何将全64位用于无符号整数?
我正在尝试找到无符号 64 位 int 的前导位。我正在使用 BSR,因为我的处理器没有 LZCNT 指令。我的问题是,一旦输入正好是 2^32,它就会返回 2^64 作为前导位值,然后循环返回输出,直到 2^64。
这是我的代码:
unsigned long int LeadingBit(unsigned long int a) {
if(a==0)
return 0;
unsigned long int nlb;
asm (
"BSR %1, %0 \n"
: "=r" (nlb)
: "mr" (a)
: "cc"
);
return 1<<nlb;
}
Run Code Online (Sandbox Code Playgroud)
这段代码的目的是能够输入一个64位整数,并让它返回前导1的位置的值。例如:a = 65(1000001)返回1000000。