我一直在研究一个(C++)项目,它需要完全动态分配的函数,这意味着malloc/new和mprotect,然后手动修改缓冲区到汇编代码.因此我完全想知道,我的这个"缓冲区"需要什么,因为它是任何其他_cdecl函数的复制品.例如:
int ImAcDeclFunc(int a, int b)
{
return a + b;
}
Run Code Online (Sandbox Code Playgroud)
如果我想从字面上创建这个函数的副本,但是完全动态,那需要什么(并记住它是带有内联汇编的C++ )?对于初学者,我想我必须做这样的事情(或类似的解决方案):
// My main....
byte * ImAcDeclFunc = new byte[memory];
mprotect(Align(ImAcDeclFunc), pageSize, PROT_EXEC | PROT_READ | PROT_WRITE);
Run Code Online (Sandbox Code Playgroud)
在此之后我将不得不找出汇编代码ImAcDeclFunc(int a, int b);.现在我在组装时仍然很糟糕,那么这个函数将如何用于AT&T语法?这是我的大胆尝试:
push %ebp
movl %%ebp, %%esp
movl 8(%ebp), %%eax
movl 12(%ebp), %%edx
addl edx, eax
pop ebp
ret
Run Code Online (Sandbox Code Playgroud)
现在如果这段代码是正确的(我非常怀疑,请纠正我)我只需要在十六进制中找到这个代码的值(例如,'jmp'是0xE9而'inc'是0xFE),并直接使用这些值C++?如果我继续以前的C++代码:
*ImAcDeclFunc = 'hex value for push'; // This is 'push' from the first line
*(uint)(ImAcDeclFunc + 1) = 'address to …Run Code Online (Sandbox Code Playgroud) 昨天我张贴这个问题上如何写一个快速自旋锁.感谢Cory Nelson,我似乎找到了一个比我的问题中讨论的其他方法更优越的方法.我使用该CMPXCHG指令来检查锁是否为0并因此是空闲的.CMPXCHG在'BYTE'上运作,WORD并且DWORD.我会假设指令运行得更快BYTE.但我写了一个实现每种数据类型的锁:
inline void spin_lock_8(char* lck)
{
__asm
{
mov ebx, lck ;move lck pointer into ebx
xor cl, cl ;set CL to 0
inc cl ;increment CL to 1
pause ;
spin_loop:
xor al, al ;set AL to 0
lock cmpxchg byte ptr [ebx], cl ;compare AL to CL. If equal ZF is set and CL is loaded into address pointed to by ebx
jnz spin_loop ;jump …Run Code Online (Sandbox Code Playgroud) 我将编写我的第一个"hello world"bootloader程序.我在CodeProject网站上找到了一篇文章.这里是它的链接.
http://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part
Up-to assembly level编程很顺利,但是当我用c编写程序时,与本文中给出的相同,我遇到了运行时错误.我的.c文件中写的代码如下.
__asm__(".code16\n");
__asm__("jmpl $0x0000,$main\n");
void printstring(const char* pstr)
{
while(*pstr)
{
__asm__ __volatile__("int $0x10": :"a"(0x0e00|*pstr),"b"(0x0007));
++pstr;
}
}
void main()
{
printstring("Akatsuki9");
}
Run Code Online (Sandbox Code Playgroud)
我使用创建了图像文件floppy.img并检查输出bochs.它显示的是这样的东西
Booting from floppy...
S
Run Code Online (Sandbox Code Playgroud)
它应该是Akatsuki9.我不知道我在哪里弄错了?任何人都可以帮我找到为什么我会遇到这个运行时错误?
我试图掌握 C 中内联汇编(ATT 汇编)的基础知识,所以我通过添加 2 个变量进行练习。
好的,这按预期工作;src变量被复制到dst变量,然后dst变量加 5。src和dst的值分别为 1 和 6 。
int src = 1;
int dst = 0;
asm ("mov %[SRC], %[DEST]\n\t"
"add $5, %0"
: [DEST] "=r" (dst));
: [SRC] "r" (src));
Run Code Online (Sandbox Code Playgroud)
但是当我尝试这个时,src和dst的值仍然是 1 和 6。我期望src的值为 1,dst的值为 5,因为将 5 添加到dst(自从 MOV 以来,dst 的值为 0)操作已被删除)应该有输出 5。
int src = 1; int dst = 0;
asm ("add $5, %[DEST]"
: [DEST] …Run Code Online (Sandbox Code Playgroud) 问题是在C函数内部我有一个内联汇编.就像是
ldr r7, =0xdeadbeef
svc 0
Run Code Online (Sandbox Code Playgroud)
如果没有显式创建文字池(这是这种情况),汇编程序会在翻译单元的末尾创建一个文字池.通常这很好,但是如果翻译单元真的很大,那么这不起作用,因为文字池离ldr指令太远了.
所以,我想知道处理这个问题的最佳方法是什么.最明显的方法是在内联汇编中手动创建文字池:
ldr r7, =0xdeadbeef
svc 0
b 1f
.ltorg
1:
Run Code Online (Sandbox Code Playgroud)
要么
ldr r7, 1f
svc 0
b 2f
1:
.word 0xdeadbeef
2:
Run Code Online (Sandbox Code Playgroud)
不幸的是,由于冗余分支指令,这导致了次优代码.我不希望汇编器足够聪明,为函数内部的常量池找到合适的位置.我想要做的是在函数的末尾创建一个常量池.有没有办法告诉编译器(gcc)在函数末尾创建一个文字池?
PS我最终使用了movw/movt对而不是常量池.虽然,首先,movw/movt解决方案的可移植性略低于文字池,其次,我只是想知道是否可以可靠而有效地在内联汇编中使用常量池.
更新: 那么,处理问题的最佳方法是什么?
要强制工具链在函数之后创建一个常量池,可以将函数放在单独的代码部分中.它的工作原理是因为在翻译单元结束时汇编程序为每个部分生成单独的常量池.
实际上,最好的方法是避免将常量加载到内联汇编中的寄存器中.让编译器这样做会更好.在我的情况下,我最终写了一个类似的代码
register int var asm("r7") = 0xdeadbeef;
asm volatile("svc 0\n" :: "r" (var));
Run Code Online (Sandbox Code Playgroud) 在代码中,我有以下声明
#if GCC == 1
#define SET_STACK(s) asm("movl temp,%esp");
...
#endif
Run Code Online (Sandbox Code Playgroud)
在代码中,恰好在一个地方,使用这个宏,编译器在哪个行上指示undefined reference to 'temp'.
temp = (int*)some_pointer;
SET_STACK(temp);
Run Code Online (Sandbox Code Playgroud)
该temp变量声明为全球挥发性空指针
volatile void* temp;
Run Code Online (Sandbox Code Playgroud)
内联汇编有什么语法问题吗?根据我的理解,内联汇编尝试加载temp(不是取消引用的值,而是指针本身)的值
我一直在玩D的内联汇编程序和SSE,但发现了一些我不理解的东西.当我尝试在声明后立即添加两个float4向量时,计算是正确的.如果我把计算放在一个单独的函数中,我得到一系列的nans.
//function contents identical to code section in unittest
float4 add(float4 lhs, float4 rhs)
{
float4 res;
auto lhs_addr = &lhs;
auto rhs_addr = &rhs;
asm
{
mov RAX, lhs_addr;
mov RBX, rhs_addr;
movups XMM0, [RAX];
movups XMM1, [RBX];
addps XMM0, XMM1;
movups res, XMM0;
}
return res;
}
unittest
{
float4 lhs = {1, 2, 3, 4};
float4 rhs = {4, 3, 2, 1};
println(add(lhs, rhs)); //float4(nan, nan, nan, nan)
//identical code starts here
float4 res;
auto …Run Code Online (Sandbox Code Playgroud) AVX512为其算术命令引入了opmask功能。一个简单的示例:godbolt.org。
#include <immintrin.h>
__m512i add(__m512i a, __m512i b) {
__m512i sum;
asm(
"mov ebx, 0xAAAAAAAA; \n\t"
"kmovw k1, ebx; \n\t"
"vpaddd %[SUM] %{k1%}%{z%}, %[A], %[B]; # conditional add "
: [SUM] "=v"(sum)
: [A] "v" (a),
[B] "v" (b)
: "ebx", "k1" // clobbers
);
return sum;
}
Run Code Online (Sandbox Code Playgroud)
-march=skylake-avx512 -masm=intel -O3
Run Code Online (Sandbox Code Playgroud)
mov ebx,0xaaaaaaaa
kmovw k1,ebx
vpaddd zmm0{k1}{z},zmm0,zmm1
Run Code Online (Sandbox Code Playgroud)
问题是必须指定k1。
是否有类似于"r"整数的输入约束,除了它选择k寄存器而不是通用寄存器外?
我有 2 个变量来模拟 X86 XMM 和 YMM,如下所示:
uint64_t xmm_value[2];
uint64_t ymm_value[4];
Run Code Online (Sandbox Code Playgroud)
现在我想使用内联汇编来读取和写入 XMM/YMM 寄存器。
xmm_value到寄存器XMM0?YMM0到ymm_value?我已经尝试搜索示例内联汇编来执行此操作,但找不到任何好的答案。谢谢!
因此,在一些帮助下,我编写了这段代码,并且编译正常。我用于movupsXMM 和vmovupsYMM,如下所示。这是正确的吗?我还可以优化我的代码吗?
__m128 xmm0;
__m256 ymm0;
// write to XMM0, and read from YMM0
__asm__("movups %1, %%xmm0\n\t"
"vmovups %%ymm0, %0"
: "=m"(ymm0)
: "m"(xmm0)
: "xmm0", "ymm0");
Run Code Online (Sandbox Code Playgroud)
更新 2:这是我的完整代码(添加了 vpbroadcastb)
__m128 xmm0;
__m256 ymm0;
// write to XMM0, and read from YMM0
__asm__("movups %1, %%xmm0\n\t"
"vpbroadcastb %%xmm0, %%ymm0\n\t"
"vmovups …Run Code Online (Sandbox Code Playgroud) 我真的不喜欢 GNU 汇编器语法,并且我使用 NASM 语法编写的一些现有代码移植起来会非常痛苦且耗时。
是否可以使global_asm!()宏使用 NASM 作为汇编程序或使 GAS 使用 NASM 语法?