我对.NET语言环境中的机器代码和本机代码感到困惑.
他们之间有什么区别?它们是一样的吗?
我正在用这个把我的头撞到墙上。
在我的项目中,使用mmap映射(/proc/self/maps)分配内存时,尽管我只请求了可读内存,但它仍是一个可读且可执行的区域。
在研究了strace(看起来不错)和其他调试之后,我能够确定似乎唯一可以避免这个奇怪问题的东西:从项目中删除程序集文件,只保留纯C。(什么?!)
所以这是我一个奇怪的例子,我正在使用Ubunbtu 19.04和默认的gcc。
如果使用ASM文件(为空)编译目标可执行文件,则将mmap返回一个可读和可执行区域,如果构建时没有该区域,则它将正常运行。请参阅/proc/self/maps示例中已嵌入的输出。
example.c
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
int main()
{
void* p;
p = mmap(NULL, 8192,PROT_READ,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);
{
FILE *f;
char line[512], s_search[17];
snprintf(s_search,16,"%lx",(long)p);
f = fopen("/proc/self/maps","r");
while (fgets(line,512,f))
{
if (strstr(line,s_search)) fputs(line,stderr);
}
fclose(f);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
example.s:是一个空文件!
产出
附带ASM版本
VirtualBox:~/mechanics/build$ gcc example.c example.s -o example && ./example
7f78d6e08000-7f78d6e0a000 r-xp 00000000 00:00 0
Run Code Online (Sandbox Code Playgroud)
没有ASM随附的版本
VirtualBox:~/mechanics/build$ gcc example.c -o example && ./example
7f1569296000-7f1569298000 …Run Code Online (Sandbox Code Playgroud) 上面的话题让我做一些实验与bool和int的if状态.所以出于好奇我写了这个程序:
int f(int i)
{
if ( i ) return 99; //if(int)
else return -99;
}
int g(bool b)
{
if ( b ) return 99; //if(bool)
else return -99;
}
int main(){}
Run Code Online (Sandbox Code Playgroud)
g++ intbool.cpp -S 为每个函数生成asm代码,如下所示:
asm代码 f(int)
__Z1fi:
LFB0:
pushl %ebp
LCFI0:
movl %esp, %ebp
LCFI1:
cmpl $0, 8(%ebp)
je L2
movl $99, %eax
jmp L3
L2:
movl $-99, %eax
L3:
leave
LCFI2:
ret
Run Code Online (Sandbox Code Playgroud)asm代码 g(bool)
__Z1gb:
LFB1:
pushl %ebp
LCFI3: …Run Code Online (Sandbox Code Playgroud)我做了一些研究.一个字节是8位,一个字是可以在内存中寻址的最小单元.单词的确切长度会有所不同.我不明白的是有一个字节是什么意思?为什么不说8位?
我问过这个问题的教授,他说这些天大多数机器都是字节可寻址的,但这会产生什么结果呢?
我是汇编语言的初学者,并注意到编译器发出的x86代码通常在释放/优化模式下保持帧指针,当它可以使用EBP寄存器时.
我理解为什么帧指针可能使代码更容易调试,并且如果alloca()在函数内调用则可能是必要的.但是,x86只有很少的寄存器,并使用其中两个寄存器来保存堆栈帧的位置,当一个就足够了,对我来说没有意义.为什么即使在优化/发布版本中省略框架指针也是一个坏主意?
我想拆解我的可启动x86磁盘的MBR(前512字节).我已经将MBR复制到了一个文件中
dd if=/dev/my-device of=mbr bs=512 count=1
Run Code Online (Sandbox Code Playgroud)
对可以反汇编文件的Linux实用程序的任何建议mbr?
我对那里的所有核心低级黑客都有疑问.我在博客中遇到了这句话.我并不认为这些来源很重要(如果你真的在意,那就是Haack),因为它似乎是一个常见的陈述.
例如,许多现代3D游戏都有他们用C++和Assembly编写的高性能核心引擎.
就程序集而言 - 是用汇编编写的代码,因为你不希望编译器发出额外的指令或使用过多的字节,或者你使用的是更好的算法,你无法在C中表达(或者没有表达编译器把它们搞砸了)?
我完全明白了解低级别的东西很重要.我只想在你理解它之后理解为什么程序在汇编.
在32位,我们有8个"通用"寄存器.使用64位,数量翻倍,但它似乎独立于64位变化本身.
现在,如果寄存器如此之快(没有存储器访问),为什么它们自然不存在呢?CPU构建器不应该在CPU中使用尽可能多的寄存器吗?为什么我们只有我们拥有的金额的逻辑限制是什么?
学习ASM还值得吗?
我知道一点,但我还没有真正使用它或者正确地学习它,因为我在汇编程序中学到的一切都可以用1/10的时间用C或C++这样的语言来完成.那么,我应该真正学习和使用ASM吗?这对我有什么好的专业吗?它会增加我的机智吗?总之,它会让我成为更好的程序员吗?
注意:我说的是像FASM或NASM这样的低级程序集,而不是像HLA(高级汇编程序)这样的程序.
所以我知道以下寄存器及其用途应该是什么:
CS =代码段(用于IP)
DS =数据段(用于MOV)
ES =目标段(用于MOVS等)
SS =堆栈段(用于SP)
但是以下哪些寄存器用于什么?
FS ="文件段"?
GS = ???
注意:我不是在询问任何特定的操作系统 - 我问的是CPU的用途是什么,如果有的话.