在x86-64架构中,两个寄存器具有特殊用途:FS和GS.在linux 2.6.*中,FS寄存器似乎用于存储线程本地信息.
我最近升级了ac #windows服务,以64位.net进程运行.通常,这将是微不足道的,但系统使用了用C++编写的32位DLL.它不能将此DLL转换为64位,因此我将DLL封装在一个单独的32位.net进程中,并通过远程处理暴露了.net接口.
这是一个非常可靠的解决方案,但我更愿意将系统作为单个进程运行.有没有什么办法可以将我的32位DLL加载到64位进程并直接访问它(可能通过某种thunking层)?
编译以下代码片段时(clang x86-64 -O3)
std::array<int, 5> test()
{
std::array<int, 5> values {{0, 1, 2, 3, 4}};
return values;
}
Run Code Online (Sandbox Code Playgroud)
它产生了我期望的典型装配
test(): # @test()
mov rax, rdi
mov ecx, dword ptr [rip + .L__const.test().values+16]
mov dword ptr [rdi + 16], ecx
movups xmm0, xmmword ptr [rip + .L__const.test().values]
movups xmmword ptr [rdi], xmm0
ret
.L__const.test().values:
.long 0 # 0x0
.long 1 # 0x1
.long 2 # 0x2
.long 3 # 0x3
.long 4 # 0x4
Run Code Online (Sandbox Code Playgroud)
但是对于小型阵列,似乎已经找到了窍门?
std::array<int, 3> test()
{ …Run Code Online (Sandbox Code Playgroud) 我想拿起一点x86.我正在使用gcc -S -O0在64位mac上进行编译.
C中的代码:
printf("%d", 1);
Run Code Online (Sandbox Code Playgroud)
输出:
movl $1, %esi
leaq LC0(%rip), %rdi
movl $0, %eax ; WHY?
call _printf
Run Code Online (Sandbox Code Playgroud)
我不明白为什么在调用'printf'之前%eax被清除为0.由于printf返回打印的字符数量为%eax我最好的猜测,因此将其归零以准备它,printf但我认为printf必须负责准备它.而且,相反,如果我调用自己的功能int testproc(int p1),则gcc认为没有必要准备%eax.所以我想知道为什么gcc对待printf和testproc不同.
在本文件中.27它说文本段从0x400000开始.为什么选择这个特定的地址?有什么理由吗?相同的地址被选择在GNU ld上Linux:
$ ld -verbose | grep -i text-segment
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
Run Code Online (Sandbox Code Playgroud)
这是令人惊讶的,因为这个地址在32位x86可执行文件中更大:
$ ld -verbose | grep -i text-segment
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS;
Run Code Online (Sandbox Code Playgroud)
我读了这个问题,讨论为什么为i386选择了0x080xxxxx地址,但它没有解释x86_64的变化.在这个问题上很难找到任何解释.有人有线索吗?
我想定义一个有效的整数下限函数,即从float或double转换为向负无穷大执行截断。
我们可以假设这些值使得没有整数溢出发生。到目前为止,我有一些选择
转换为int 这需要对负值进行特殊处理,因为转换会截断为零。
I= int(F); if (I < 0 && I != F) I--;
Run Code Online (Sandbox Code Playgroud)将floor的结果转换为int;
int(floor(F));
Run Code Online (Sandbox Code Playgroud)强制转换为int以获得较大的正数(对于较大的值,这可能会返回错误的结果);
int(F + double(0x7fffffff)) - 0x7fffffff;
Run Code Online (Sandbox Code Playgroud)众所周知,将数据类型转换为int很慢。如果测试也是如此。我尚未设置发言权功能的时间,但是看到帖子声称它也很慢。
您能在速度,准确性或允许范围方面考虑更好的替代方法吗?它不需要是便携式的。目标是最新的x86 / x64体系结构。
我有以下 C/C++ 函数:
unsigned div3(unsigned x) {
return x / 3;
}
Run Code Online (Sandbox Code Playgroud)
使用 clang 10 at编译时-O3,结果为:
div3(unsigned int):
mov ecx, edi # tmp = x
mov eax, 2863311531 # result = 3^-1
imul rax, rcx # result *= tmp
shr rax, 33 # result >>= 33
ret
Run Code Online (Sandbox Code Playgroud)
我所理解的是:除以 3 相当于乘以乘法逆 3 -1 mod 2 32,即 2863311531。
不过还是有些不明白的地方:
ecx/rcx呢?我们不能乘rax用edi直接?eaxand不是更快ecx吗?imul …发现(无法访问源项目).NET程序集DLL是否编译为"x86","x64"或"任何CPU"的最简单方法是什么?
更新:命令行实用程序足以满足我的直接需求,但仅仅是为了完整性,如果有人想告诉我如何以编程方式执行它,那么这也是有意义的,我敢肯定.
0x0000000000400507 <main+28>: 74 0c je 0x400515 <main+42>
0x0000000000400509 <main+30>: bf 28 06 40 00 mov $0x400628,%edi
..
0x400507 <main+28>: 0x28bf0c74
Run Code Online (Sandbox Code Playgroud)
我的结论是对的吗?
在Intel 64架构中,有rax..rdx寄存器,它们只是A..D通用寄存器.
但是也有一些名为rsi和rdi的寄存器,它们是"源索引"和"目标索引"寄存器.为什么这些寄存器有实际名称(与A等相比)?
"源索引"和"目标索引"实际上意味着什么?是否有一些惯例说这些寄存器应该在特定情况下使用?
x86-64 ×10
assembly ×4
c++ ×3
.net ×2
abi ×2
linux ×2
64-bit ×1
architecture ×1
compilation ×1
elf ×1
endianness ×1
floor ×1
gcc ×1
macos ×1
memory ×1
performance ×1
windows ×1
x86 ×1