Articles of x86 64

在uint128_t整数的上下文中对hexstring进行操作

标准Linux库函数strtoull是64位。 是否存在针对在uint128_t整数上运行的Linux x86_64环境的strtoX familyfunction的实现? 可能的原型: uint128_t strtoulll(const char *nptr, char **endptr, int base); 另外,如何使用printf / sprintf打印uint128_t整数?

如果ASLR被禁用,mmap是确定性的吗?

如果地址空间布局随机化(ASLR)被禁用,我们是否有确定性的mmap ? 通过确定性,我的意思是说,如果我用相同的input一次又一次地运行相同的应用程序,我会得到相同的地址由mmap返回? 我最感兴趣的是匿名的mmap。

Linux / x86-64系统调用中的结构体对于汇编程序员的布局?

许多linux / x86-64系统调用接受指向结构的指针作为参数。 例如stat(2)的第二个参数是struct stat* … struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; […]

在64位Linux上从32位模式切换到64位(长模式)

我的程序是在x86_64 CPU(64位操作系统,Ubuntu 8.04)上运行的32位模式。 是否可以暂时在用户模式下切换到64位模式(长时间模式)? 如果是这样,怎么样? 背景故事:我正在写一个链接到32位模式程序的库,所以它在启动时必须是32位模式。 但是,我想使用更快的x86_64入侵以获得更好的性能。 所以我想切换到64位模式做一些纯粹的计算(没有操作系统的交互;不需要64位寻址),返回到32位,然后返回给调用者。 我发现有一些相关但不同的问题。 例如, 在64位程序中运行32位代码 在32位操作系统中运行64位代码 我的问题是“在32位程序,64位操作系统中运行64位代码”

Linux在x86-64中如何支持超过512GB的虚拟地址范围?

用于Linux的x86-64的用户虚拟地址空间是47位长。 这基本上意味着Linux可以映射具有大约128 TB的虚拟地址范围的进程。 然而,我认为x86-64体系结构支持ISA为每个进程定义了4级分层页表(排列为基数树)。 页表的根目录最多只能映射512 GB的连续虚拟地址空间。 那么Linux如何能够支持超过512GB的虚拟地址范围呢? 它是否为每个进程使用多个页表? 如果是的话,那么对于一个进程来说,CR3(x86-64的寄存器包含页表的基地址)应该包含什么给定的进程? 我错过了什么吗?

为什么gcc强制PIC为x64共享库?

试图用gcc将非PIC代码编译到x64上的共享库中会导致错误,如下所示: /usr/bin/ld: /tmp/ccQ2ttcT.o: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC 这个问题是关于为什么这样。 我知道x64具有RIP相对寻址function,旨在提高PIC代码的效率。 但是,这并不意味着加载时重定位不能(理论上)适用于这样的代码。 一些在线资源(包括在这个问题上被广泛引用)声称, 由于 RIP相对寻址,共享库中的非PIC代码有一些固有的限制。 我不明白为什么这是真的。 考虑“旧x86” – 一个call指令也有一个IP相对操作数。 然而, call它的x86代码在没有PIC的情况下编译成共享库,但使用加载时重定位 R_386_PC32 。 对于x64中的数据RIP相对寻址,不能这样做吗? 请注意,我完全理解PIC代码的好处,并且性能降低了RIP相对寻址有助于缓解。 不过,我很好奇不允许使用非PIC代码的原因。 是否有一个真正的技术背后的原因,还是只是鼓励编写PIC代码?

页面错误陷阱的成本

我有一个应用程序定期(每1或2秒后)通过分叉自己的检查点。 所以检查点是原始进程的一个分支,它只是保持空闲,直到在原始进程中出现错误时要求启动。 现在我的问题是fork的copy-on-write机制是多么昂贵。 写入时复制机制将确保原始进程写入内存页面(在获得检查点之后的第一次)时,将发生的页面错误陷阱的成本是多less与检查点不同的物理页面。 在我看来,页面错误陷阱开销可能会相当高,因为中断发生时,我们从用户空间降落到内核空间,然后从内核回到用户空间。 我可以从这样的页面错误陷阱中损失多lessCPU周期。 假设RAM足够大,我们不需要交换到硬盘。 那么我知道,很难想象一个检查点计划比这更有效率,因此你可以说为什么我担心页面陷阱错误的开销,但我只是想知道这个计划将有多less成本。

什么是“mov rax,QWORD PTR fs:0x28”汇编指令呢?

在执行该指令之前,fs包含0x0。 另外我想知道我怎么能从GDB的这个内存区读取,这个命令是什么?

SMP如何处理中断?

在SMP(Symmetrix多处理器/多核)机器上如何处理中断? 是否只有一个内存pipe理单元? 假设有两个线程,运行在不同内核上的A和B触及页表中不存在的内存页面(同时),在这种情况下会出现页面错误,并从内存中引入新页面。 什么是将发生的事件序列? 如果有一个内存pipe理单元,哪个核心是页面错误转发的? 内核如何处理它? 是否有多个内核实例,每个实例都运行在不同的内核上? 如果是这样,他们如何同步页面error handling等事件?

上证所:跨越页面边界的未alignment的加载和存储

我在某处读取了在执行未alignment的加载或存储在页面边界旁边(例如使用_mm_loadu_si128 / _mm_storeu_si128内在函数)之前,代码应该首先检查整个向量(本例中为16字节)是否属于同一页面,并切换到非向量指令如果不。 我明白,如果下一页不属于进程,则需要防止coredump。 但是,如果这两个页面属于进程(例如,它们是一个缓冲区的一部分,并且我知道该缓冲区的大小)呢? 我写了一个小的testing程序,执行跨越页面边界的未alignment的加载和存储,并没有崩溃。 在这种情况下,我是否必须经常检查页面边界,还是足以确保我不会溢出缓冲区? Env:Linux,x86_64,gcc