我希望学习x86的汇编语言.我在Mac上,我假设大多数x86教程/书籍都使用适用于Windows的代码.
运行代码的操作系统如何影响代码的作用,或者确定代码是否有效?我可以遵循基于Windows的教程,并修改一些命令,使其适用于Mac相对容易吗?更一般地说,Mac程序集程序员,特别是应该知道的是否有什么棘手的问题?谢谢!
有没有人有关于学习Linux x86-64程序集基础知识的文档?我不确定是否要按原样学习它,或者先学习x86,然后再学习它,但是因为我有一台x86-64计算机而不是x86,我正在考虑学习x86-64; )
也许有人可以给我一些激励,并指导学习什么,如何以及用什么文档.
请给我你最喜欢的文档标题,我编写一些Python,这是我第一次尝试低级语言,而且我已经准备好专注于它.
谢谢大家
我们如何在x86 Linux中直接使用sysenter/syscall实现系统调用?有人可以提供帮助吗?如果您还可以显示amd64平台的代码,那就更好了.
我知道在x86中,我们可以使用
__asm__(
" movl $1, %eax \n"
" movl $0, %ebx \n"
" call *%gs:0x10 \n"
);
Run Code Online (Sandbox Code Playgroud)
间接路由到sysenter.
但是我们如何使用sysenter/syscall直接编码来发出系统调用呢?
我找到了一些材料http://damocles.blogbus.com/tag/sysenter/.但仍然难以弄明白.
我目前正在研究如何实现一个沙盒(类似于谷歌的NaCl项目),在那里我可以运行不受信任的x86代码(受限制的指令集),这样它就不会损害我的其余进程.
与NaCl不同,不受信任的代码不会在单独的进程中运行,而是与主机应用程序运行相同的进程.因此,一个关键步骤是使Windows的结构化异常处理正确,以便捕获错误(如无效的内存访问或div为0),并在Windows杀死我的主机应用程序之前正常终止沙箱.(NaCl不会遇到这些问题.沙箱是一个单独的过程,如果出现错误就会被杀死.)
此外,沙盒代码不应使用宿主应用程序堆栈,而是在我自己分配的某个单独的"堆栈"上运行.
正是这种组合(存在自定义分配堆栈时的异常处理)扭曲了我的想法.我已经检查了Go和Factor的语言实现,它们做了类似的事情并且通过这个帮助得到了一些运行.
但仍有一些悬而未决的问题和不确定因素.所以我想我会利用Stack Overflow的神奇知识来获得一些意见:-)
以下是一个工作代码片段,内容涉及核心问题:
code.cpp
#include <Windows.h>
extern "C" void Sandbox();
// just a low level helper to print "msg"
extern "C" void Write(const char* msg)
{
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),
msg, (DWORD)strlen(msg), NULL, NULL);
}
// should be called first on error and continue exception handling
LONG __stdcall GlobalExceptionHandler(_EXCEPTION_POINTERS*)
{
Write("GEH ");
return EXCEPTION_CONTINUE_SEARCH;
}
// should be called afterwards on error and terminate the process
// of course this is just a …Run Code Online (Sandbox Code Playgroud) 我正在阅读:http: //gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
它首先表明:与-flto结合使用此选项(-fwhole-program)不应该使用.相反,依赖链接器插件应该提供更安全和更精确的信息.
然后,它表明:如果程序不需要导出任何符号,则可以将-flto和-fwhole-program结合使用,以允许过程间优化器使用更积极的假设,这可能会改善优化机会.当链接器插件处于活动状态时,不需要使用-fwhole-program(请参阅-fuse-linker-plugin).
这是否意味着在理论上,使用-fuse-linker-plugin和-flto总是得到比使用-fwhole-program with -flto更好的可执行文件?
我尝试使用ld 分别与-fuse -linker-plugin和-fwhole-program 链接,并且可执行文件的大小至少是不同的.
提前致谢.
PS我在CentOS 6上使用gcc 4.6.2和ld 2.21.53.0.1.
我试图在i7上以最有效的方式计算浮点数和位向量之间的点积.实际上,我在128或256维向量上进行此操作,但为了说明,让我编写64维代码来说明问题:
// a has 64 elements. b is a bitvector of 64 dimensions.
float dot(float *restrict a, uint64_t b) {
float sum = 0;
for(int i=0; b && i<64; i++, b>>=1) {
if (b & 1) sum += a[i];
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
当然,这是有效的,但问题是,这是整个程序的时间要点(占用50分钟运行的95%CPU时间)所以我迫切需要让它更快.
我的猜测是上面的分支是游戏杀手(防止无序执行,导致坏分支预测).我不确定矢量指令是否可以在这里使用和帮助.使用gcc 4.8和-std = c99 -march = native -mtune = native -Ofast -funroll-loops,我现在得到这个输出
movl $4660, %edx
movl $5, %ecx
xorps %xmm0, %xmm0
.p2align 4,,10
.p2align 3
.L4:
testb $1, %cl
je .L2
addss (%rdx), %xmm0
.L2:
leaq …Run Code Online (Sandbox Code Playgroud) 我是这里的新手,刚刚开始学习汇编语言.所以,如果我错了,请纠正我,或者如果这篇文章没有任何意义我会删除.
我在讨论x86-64英特尔架构中的数据移动指令.我已经读过,常规movq指令只能有直接的源操作数,可以表示为32位二进制补码数,而movabsq指令可以有任意64位立即数作为其源操作数,并且只能有一个寄存器作为目标.
你能详细说明一下吗?这是否意味着我只能使用movabsq指令移动64位立即值?只有立即价值到登记册?我不知道如何将64位立即值移动到内存中.或者也许我错了一些重要的事情.
如您所知,Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE为了防止出现负值,该safeAbs方法已在我的项目中实现:
public static int safeAbs(int i) {
i = Math.abs(i);
return i < 0 ? 0 : i;
}
Run Code Online (Sandbox Code Playgroud)
我将性能与以下各项进行了比较:
public static int safeAbs(int i) {
return i == Integer.MIN_VALUE ? 0 : Math.abs(i);
}
Run Code Online (Sandbox Code Playgroud)
并且第一个比第二个慢几乎6倍(第二个性能几乎与“纯” Math.abs(int)相同)。从我的角度来看,字节码没有显着差异,但是我猜想差异存在于JIT“汇编”代码中:
“慢”版本:
0x00007f0149119720: mov %eax,0xfffffffffffec000(%rsp)
0x00007f0149119727: push %rbp
0x00007f0149119728: sub $0x20,%rsp
0x00007f014911972c: test %esi,%esi
0x00007f014911972e: jl 0x7f0149119734
0x00007f0149119730: mov %esi,%eax
0x00007f0149119732: jmp 0x7f014911973c
0x00007f0149119734: neg %esi
0x00007f0149119736: test %esi,%esi
0x00007f0149119738: jl 0x7f0149119748
0x00007f014911973a: mov %esi,%eax
0x00007f014911973c: add $0x20,%rsp …Run Code Online (Sandbox Code Playgroud) 我正在hacks.mozilla.org上阅读64位Firefox版本的博客.
作者说:
对于
asm.js代码,增加的地址空间还允许我们使用硬件内存保护来安全地从asm.js堆访问中删除边界检查.收益非常显着:asmjs-apps上的8%-17%- * - arewefastyet.com上报告的吞吐量测试.
我试图了解64位硬件如何对C/C++进行自动边界检查(假设编译器支持硬件).我在SO中找不到任何答案.我找到了一篇关于这个主题的技术论文,但我无法理解这是怎么做到的.
有人可以在边界检查中解释64位硬件辅助吗?
我有类似的东西:
if (f = acquire_load() == ) {
... use Foo
}
Run Code Online (Sandbox Code Playgroud)
和:
auto f = new Foo();
release_store(f)
Run Code Online (Sandbox Code Playgroud)
您可以很容易地想象使用atomic with load(memory_order_acquire)和store(memory_order_release)的acquire_load和release_store的实现.但是现在如果release_store是用_mm_stream_si64实现的,这是一个非临时写入,而不是针对x64上的其他商店进行排序的?如何获得相同的语义?
我认为以下是最低要求:
atomic<Foo*> gFoo;
Foo* acquire_load() {
return gFoo.load(memory_order_relaxed);
}
void release_store(Foo* f) {
_mm_stream_si64(*(Foo**)&gFoo, f);
}
Run Code Online (Sandbox Code Playgroud)
并使用它:
// thread 1
if (f = acquire_load() == ) {
_mm_lfence();
... use Foo
}
Run Code Online (Sandbox Code Playgroud)
和:
// thread 2
auto f = new Foo();
_mm_sfence(); // ensures Foo is constructed by the time f is published to gFoo
release_store(f)
Run Code Online (Sandbox Code Playgroud)
那是对的吗?我非常肯定这里绝对需要sfence.但是那个lfence怎么样?是否需要或者简单的编译器障碍对于x64是否足够?例如asm volatile("":::"memory").根据x86内存模型,负载不会与其他负载重新排序.所以根据我的理解,只要存在编译器障碍,acquire_load()必须在if语句中的任何加载之前发生.