我有一个用我的C代码编写的小内联汇编代码.asm遍历数组,如果需要,将值从不同的数组移动到寄存器.最后,调用一个中断.代码类似于:
cmp arrPointer[2],1h
jne EXIT
mov AX, shortArrPtr[2]
EXIT:
int 3h
Run Code Online (Sandbox Code Playgroud)
这一切都在x86中工作,但根据microsoft:x64不支持内联汇编.如何将其全部翻译为支持x64?我找不到执行我想要的编译器内部过程,我无法弄清楚如何将参数传递给外部asm文件.
我对内联汇编程序有疑问.可以在同一个函数中从内联汇编程序调用另一个汇编程序子程序吗?例如:
void FindValidPID(unsigned int &Pid)
{
__asm
{
sub esp, 20h
mov eax, Pid
add eax,eax
call sub123 ; another assm subroutine
mov Pid, eax
add esp, 20h
}
}
Run Code Online (Sandbox Code Playgroud)
在哪里,以及如何编写子程序sub123?
干杯,
托马斯
我正在做一些实验,并希望能够在系统调用期间查看堆栈中保存的内容(用户登陆过程的已保存状态).根据http://lxr.linux.no/#linux+v2.6.30.1/arch/x86/kernel/entry_32.S它表明寄存器的各种值都保存在堆栈指针的那些特定偏移处.这是我一直试图用来检查堆栈上保存的代码的代码(这是我创建的自定义系统调用):
asm("movl 0x1C(%esp), %ecx");
asm("movl %%ecx, %0" : "=r" (value));
Run Code Online (Sandbox Code Playgroud)
其中value是unsigned long.
截至目前,该值不是预期的值(它显示为ds的用户值保存0).
我是否正确访问堆栈指针的偏移量?
另一种可能性是我可以在内核中使用调试器(如GDB)来检查堆栈内容吗?我没有广泛使用调试,也不知道如何在内核中调试代码.任何帮助深表感谢.
在32位Visual Studio C++中可以使用以下代码.是否有使用内在函数的64位等效项,因为64位版本的Visual Studio C++不支持内联ASM?
FORCEINLINE bool bAtomicCAS8(volatile UINT8 *dest, UINT8 oldval, UINT8 newval)
{
bool result=false;
__asm
{
mov al,oldval
mov edx,dest
mov cl,newval
lock cmpxchg byte ptr [edx],cl
setz result
}
return(result);
}
Run Code Online (Sandbox Code Playgroud)
以下instrinsics在Visual Studio C++下编译
_InterlockedCompareExchange16
_InterlockedCompareExchange
_InterlockedCompareExchange64
_InterlockedCompareExchange128
Run Code Online (Sandbox Code Playgroud)
我正在寻找的是什么
_InterlockedCompareExchange8
Run Code Online (Sandbox Code Playgroud)
但这似乎并不存在.
这是我的代码:
void Graph::PutPixel(DWORD x, DWORD y, DWORD c)
{
__asm
{
Mov Eax, y
Mov Ebx, _width
Mul Ebx
Add Eax, x
Shl Eax, 2 // Multiply by four
Add Eax, _buffer
Mov Edi, Eax
Mov Eax, c
StosD
}
}
Run Code Online (Sandbox Code Playgroud)
_buffer和_width是Graph类成员:
private:
DWORD _width;
DWORD* _buffer;
Run Code Online (Sandbox Code Playgroud)
这是行不通的; 我从两个变量得到0值,但实际上它们还有其他一些值.
我可以通过将类变量复制到局部变量并使用它们来解决它:
void Graph::PutPixel(DWORD x, DWORD y, DWORD c)
{
DWORD bufAddr = (DWORD)_buffer;
DWORD w = _width;
__asm
{
Mov Eax, y
Mov Ebx, w
Mul Ebx
Add Eax, x
Shl …Run Code Online (Sandbox Code Playgroud) 根据MSDN文档,当使用类函数的默认__thiscall调用约定时,"this"指针存储在ECX中.尽管在翻译常规C++代码时肯定会出现这种情况,但在尝试使用内联汇编访问"this"时遇到了问题.
这是测试程序:
#include <cstdio>
class TestClass
{
long x;
public:
inline TestClass(long x):x(x){}
public:
inline long getX1(){return x;}
inline long getX2()
{
_asm
{
mov eax,dword ptr[ecx]
}
}
};
int main()
{
TestClass c(42);
printf("c.getX1() = %d\n",c.getX1());
printf("c.getX2() = %d\n",c.getX2());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
两个Get函数的翻译如下:
?getX1@TestClass@@QAEJXZ (public: long __thiscall TestClass::getX1(void)):
00000000: 8B 01 mov eax,dword ptr [ecx]
00000002: C3 ret
?getX2@TestClass@@QAEJXZ (public: long __thiscall TestClass::getX2(void)):
00000000: 8B 01 mov eax,dword ptr [ecx]
00000002: C3 ret
Run Code Online (Sandbox Code Playgroud)
我认为这两个功能完全相同是可以肯定的.不过,这是程序的输出:
c.getX1() = …Run Code Online (Sandbox Code Playgroud) 我正在尝试为高度优化的x86-64位操作代码编写一个小型库,并且正在摆弄内联asm.
在测试这个特殊情况时引起了我的注意:
unsigned long test = 0;
unsigned long bsr;
// bit test and set 39th bit
__asm__ ("btsq\t%1, %0 " : "+rm" (test) : "rJ" (39) );
// bit scan reverse (get most significant bit id)
__asm__ ("bsrq\t%1, %0" : "=r" (bsr) : "rm" (test) );
printf("test = %lu, bsr = %d\n", test, bsr);
Run Code Online (Sandbox Code Playgroud)
在gcc和icc中编译并运行良好,但是当我检查程序集时,我会得到差异
gcc -S -fverbose-asm -std=gnu99 -O3
movq $0, -8(%rbp)
## InlineAsm Start
btsq $39, -8(%rbp)
## InlineAsm End
movq -8(%rbp), %rax
movq %rax, -16(%rbp)
## …Run Code Online (Sandbox Code Playgroud) 我试图在GCC样式扩展asm(x86-64目标)中编写我的一小段代码,并且在编码结构偏移时遇到问题.
我有一个struct s成员size_t a[],一个指向这样的结构和索引的指针,这两个结构都是在asm块中生成的.
现在我需要在asm中解决这个问题
asm (
"mov %[displ](%[s], %[index], 8), %%rbx"
: [s] "+r" (s)
, [index] "+r" (i)
: "memory", "cc", "rax", "rbx"
);
Run Code Online (Sandbox Code Playgroud)
如何编码displ到asm块?offsetof(struct s, a)作为立即前缀传递$并生成无效的程序集.
asm (
"mov %[displ](%[s], %[index], 8), %%rbx"
: [s] "+r" (s)
, [index] "+r" (i)
: [displ] "i" (offsetof(struct s, a))
: "memory", "cc", "rax", "rbx"
);
Run Code Online (Sandbox Code Playgroud) 根据扩展汇编程序的gcc文档:
当操作数的约束允许寄存器时,您应该只使用读写操作数.
这似乎是非常明确的:你不能使用+ m作为输出.
但是,我已经看过很多次了.事实上,Linus Torvalds有记录说
gcc文档是次要的.他们没有更新,他们不正确,他们没有反映现实,他们并不重要.对于像这样的事情,唯一正确的用法是"+ m"
如果编译器最终搞砸了我的代码,我不想使用+ m.甚至检查输出asm以确定它是否正常工作并不意味着明天当我改变一些看似无关的东西时它仍然会起作用.或者当我获得gcc的下一次更新时它仍然可以工作.
如果文档是正确的,我不能依赖于这种正常工作,我想知道,所以我可以寻求其他选择(其中大多数是令人不快的痛苦).如果文档错误,请告诉我如何纠正它们.
我正在编写一些代码,其中非常需要从嵌入式asm块中获取条件标志,并将其用作在调用C代码中分支的条件。我不想存储标志(那将是无用的且效率低下的;已经有更有效的方法来实现结果),而是直接使用标志。有什么方法可以使用GNU C内联asm约束来实现这一目标?我对适用于多种指令集体系结构的方法感兴趣,目的是将其与体系结构的LL / SC样式原子产生的条件标志一起使用。当然,另一个明显的使用情况(与我正在做的事情不同)是允许外部C代码在内联asm中的操作的进位标志结果上分支。
inline-assembly ×10
assembly ×5
c ×4
c++ ×4
gcc ×4
64-bit ×2
visual-c++ ×2
x86-64 ×2
i386 ×1
icc ×1
linux ×1
optimization ×1
system-calls ×1
this ×1
x86 ×1