在AMD 64位模式下的分段限制检查
我正在为64位处理器编写自己的操作系统,并且遇到了一般保护问题.我的操作系统将不依赖页面故障来实现用户空间保护机制,因此我发现有一种方法可以使用段限制检查: vmware的此演示 /a> 第20页说: 初始AMD64体系结构不包括64位模式下的分割 EMT64T也缺少分段 我们如何保护VMM? 64位的客人支持需要其他硬件协助 在较新的AMD处理器上以64位模式可用的细分限制检查 现在,我有了较新的AMD处理器模型,我的问题是如何以64位(Long)模式获得对AMD处理器的限制段限制检查?我已经下载了开发人员手册的2011年9月版本(Last),但我找不到任何位置的方法,请帮助. 解决方案 我认为他们可能在谈论"长度模式限制"启用位(LMSLE bit 13)中的"扩展功能启用寄存器"(efer)(efer)(efer)卷2 3.1.7 pg. 55 .第114页中的" 4.12.2数据限制检查"中的描述在" 4.12.2数据限制
6 2023-12-16
编程技术问答社区
对于x86-64指令,代码段描述符中的D标志有什么作用?
我试图在x86-64代码中使用时,要了解代码段描述符中D flag的工作.它在代码段描述符的D/B位22中设置,如下图所示: Intel Documentation( 3.4.5段描述符)均指定以下内容: d/b(默认操作大小/默认堆栈指针大小和/或upper 绑定)标志 根据段是否执行不同的功能 描述符是可执行的代码段,扩展数据段, 或堆栈段. (该标志应始终设置为32位的1 代码和数据段以及16位代码和数据段的0.) •可执行代码段.标志称为D标志,它 指示有效地址和操作数的默认长度 该细分市场中的指示引用.如果设置了标志,则为32位 假定地址和32位或8位操作数;如果很清楚, 假定16位地址和16位或8位操作数.这 指令前缀66H可用于选择操作数尺寸其他 比默认值和前缀67H可以选择一个地址 大小除默认外. 所以我试图了解哪些X86-64有影响? 如何? ps.当我尝试通过设置该位时运行一些测试(在Windows内核中)时,操作系统立即三重故障
4 2023-12-16
编程技术问答社区
如何在不链接 libc.so 的情况下访问段寄存器?
我正在尝试使用Ubuntu 20.10上的NASM版本2.15.04在64位组装中编码简单的堆栈金丝雀.执行以下代码在组装和链接时会导致分割故障.nasm -felf64 canary.asm && ld canary.o global _start section .text _start: endbr64 push rbp ; Save base pointer mov rbp, rsp ; Set the stack pointer call _func ; Call _func mov rdi, rax ; Save return value of _func
查找FS的内存地址:28H
我与GDB一起调试了一个乐趣,并与Stack Guard一起进行了调试,因此将Canary写入FS:28H的堆栈.出于好奇,我试图找到FS:28H点的内存地址. 我遇到了两个问题.首先,GDB无法向我展示GDTR/LDTR中的值,因为它不会以零为零.其次,当使用GDB读取fs时,它包含0,这有什么意义?我知道GDT/LDT在第一个索引中包含0,以返回无效的地址,并且RPL关闭了,所以我在这里缺少什么?如果有人知道如何找到该细分寄存器的地址,我想知道. file: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked 解决方案 您似乎正在使用x86_64-linux-gnu,即x86-64 CPU,Linux内核和GNU C库中的所有三个.使用硬件和系统软件的组合,设置了FS段,以使内存操作%fs:0是指当前执行线程的线程控制块的开头. (线程控制块是一个内部C库数据结构,描述了一
12 2023-12-16
编程技术问答社区
为什么 "分割故障 "在C语言中仍然是一个东西?
操作系统中的分割是一个与时间本身一样古老的概念.至少根据我的教授,大多数现代操作系统都抛弃了细分概念,现在主要依靠分页来实施记忆保护,从而阻止每个过程访问除自己的其他内存之外的任何其他内存.那么,我们如何仍然在C中获得"分割错误".我们是否以某种方式仍将分割作为现代操作系统的抽象概念? 解决方案 特别是在c 中,这不是一个类似Unix的OS中的东西.任何不使用内存安全的语言(可以尝试访问未上皮页面)都可以编译到可执行的segfaults.包括手写组件或福特兰.但是,是的,C和C ++是不使用内存安全的两种最广泛使用的语言. ,是的,名字是古老的; unix是 old ,并且无需可以重命名SIGSEGV,因为当用户空间通过访问内存而不会访问CPU时,内核发出的信号't地图.这样做会损坏大量使用该恒定的代码,并且仅将英语文本字符串更改为strerror/perror以使其"无效的页面故障"也不会特别有用,尽管可能是可能的我认为邮件被烤成libc.但是随后不同的LIBC版本将在转换周
8 2023-12-16
编程技术问答社区
如何用fs和gs寄存器计算有效地址
在X86_64中,FS和GS寄存器的涉及有限的分割形式.仅以FS为例,FS如何注册,FSBASE MSR一起生成有效地址? 如果我不更改FS而更改FS基础会发生什么?或更改FS基础会自动更改FS? 如果我更改FS寄存器而不更改FS基础,会发生什么?有效的地址计算如何影响? 我们可以快速示例 mov %fs:(%eax), %ebx 解决方案 FS架构寄存器与FS基本内部寄存器分开. 一如既往地,使用段覆盖只选择与该段关联的段库,而不是默认的DS基础或SS碱基(在64位模式下以0固定为0). fs架构寄存器本身的实际值与无关.仅当您要mov %fs, %eax实际读取FS寄存器本身,而不是使用与之关联的内部基础/限制"寄存器"时,它才会发挥作用. 由于有一些方法可以设置内部FS基础(例如,使用wrmsr或更新的CPU 在裸金属上,您也可以做到这一点.不要打扰使用所需的基础创建GDT条目,然后将选择器%fs或%gs mov;只需直接用wrmsr
4 2023-12-16
编程技术问答社区
段寄存器是如何参与内存地址转换的?
到目前为止我学到的有关细分的知识: 虚拟地址包含一个段选择器和偏移量 段选择器与GDTR结合使用,以找到段描述符的线性地址 该部分描述符包含有关所选段的信息,包括其线性地址 所以,我的问题是: 根据我阅读的内容,虚拟地址已加载到段寄存器中,然后以某种方式从那里继续进行翻译.将虚拟地址加载到其获取描述符中后,该片段寄存器会发生什么? 据我了解,该片段寄存器还具有描述符的缓存值.在翻译过程中,这如何发挥作用? 系统如何确定要加载的片段寄存器,鉴于片段选择器最多可以具有2^13个不同的值,并且只有六个主要寄存器? 解决方案 通常的翻译如下: Logical address --> GDT --> Linear address --> Page tables --> Physical Address (segment:offset) (segment base + offset)
2 2023-12-16
编程技术问答社区
读取包含指向列表的指针的细分寄存器(%gs)
我偶然发现了这个内核页面:,想和LD_PRELOAD一起玩LD_PRELOAD,看看我是否可以在load-lition时分配一个值并在运行时读取细分寄存器以加载值. 例如,我有两个简单的代码可以轻松地编译和执行以说明(我必须从内核网站中提供的示例代码进行一些修改): load.c用gcc -Wall -fPIC -shared -o load.so load.c -ldl -mfsgsbase 编译 #include #include #include #include #include #include /* Will be eventually in asm/hwcap.h */ #ifndef HWCAP2_FSGSBASE #define HWCAP2_FSGSBASE (1
10 2023-12-16
编程技术问答社区
在x64中完全不使用分割吗?
在x86中,当您要访问内存地址时,您将指定一个地址,该地址通过两个阶段翻译成存储地址: sementation 和 paging : 但是x64中还使用了分割吗? (我认为不使用它,但是我不确定是否在所有情况下都不使用它,或者在某些情况下使用它). 解决方案 出于您发布的图片的目的,仅在地址模式使用寄存器fs或gs时使用分割(因为这些是由Linux和Windows用非零基数积极配置的) . 分割在受保护(32位)和长(64位)模式相对于实际模式(16位)的作用明显不同. 特别是,一个段不仅是一个基础和限制,而且是一组来自两个表格(GDT或LDT)的属性. 对于所有段寄存器,但是fs和gs cpu 忽略了计算有效地址时的基础(又称偏移),该动作与对基础使用0相同的效果. 此外,对于所有细分寄存器,它都没有执行限制检查(但是线性地址必须是规范的). 值得一提的是,加载段时,cpu still stall 在GDT/LDT中加载来自段描述符的所有信息(包括基
6 2023-12-16
编程技术问答社区
为什么不能完全禁用细分市场?
根据AMD manual无法禁用分割. 我的问题是为什么,为什么不可能? 另一个问题,它说64位会禁用它,这是什么意思?分段是否在64位模式下完全禁用? AMD手册:一个> 解决方案 简介 在64位模式下,每当将非编号段选择器加载到任何片段寄存器中时,处理器都会自动在段寄存器的隐藏部分中加载相应的段描述符,就像在受保护/兼容模式下一样.但是,完全忽略了由DS,ES或SS选择器选择的段描述符.另外,FS和GS选择器选择的段描述符的限制和属性字段也被忽略. 英特尔手册v3 3.4.4: 因为ES,DS和SS段寄存器未在64位模式下使用, 他们的字段(基本,限制和属性)中的字段描述符 寄存器被忽略.某些形式的段负载指令是 也无效(例如,LDS,POP ES).解决计算 参考ES,DS或SS段被视为该段 基础为零. ... 在64位模式下,使用FS段和GS细分访问内存 未检查运行时限制的覆盖物或 属性检查. 除此之外,假定每个段的基本地址为0,长
8 2023-12-16
编程技术问答社区
在64位模式下,使用MOV指令将SS设置为0x0000是否会导致故障#GP(0)?
这个问题的灵感来自 问题:是否应该使用MOV指令将SS设置为0x0000导致一般保护故障#GP(0)在64位模式下?例如:如果我处于64位模式,当前特权级别(CPL)为0,我应该期望使用此代码段来看到#GP(0): NULL_SEL_RPL0 EQU 0 mov eax, NULL_SEL_RPL0 ; EAX = 0x0000 = NULL Selector with ; Requested Privilege Level (RPL) 0. mov ss, eax ; Try to set SS with NULL selector 0x0000 ; Should this cause a #GP(0) fault? Intel X86指令集参考参考所说的有关 Operatio
0 2023-12-16
编程技术问答社区
使用GDB来读取MSRs
是否有一些方法可以读取X86-64模型特定寄存器,特别是IA32_FS_BASE和IA32_GS_BASE,同时使用GDB调试程序? 较少可取的是使用动态仪器包(例如英特尔的Pintool)的解决方案,但将被认为是相同的. 解决方案 如果您不希望不更改代码(或者如果没有代码),则可以通过以下方式执行与AMDN的答案相似的事情.对Arch_prctl的调用需要指向UINT64_T的指针,为此,我将地址用于堆栈的空部分(当前堆栈指针以下8个字节).呼叫返回后,读取存储在该位置的8个字节值. 使用的常数:Arch_get_fs = 0x1003,Arch_get_gs = 0x1004 (gdb) p $rsp $1 = (void *)0x7fffffffe6f0 (gdb) call arch_prctl(0x1003, $rsp - 0x8) $2 = 0 (gdb) x /gx $rsp - 0x8 0x7fffffffe6e8: 0x00007f
4 2023-12-16
编程技术问答社区
关于linux x86 64的MSR_GS_BASE的详细情况
我试图找出Linux内核中宏电流的详细信息. 当前的最终组装代码是: movq %%gs:0xb000,%0 上面的代码可以工作!但是,当我打印%% GS时,其值为0,因此%% GS指向GDT NULL的第一项!它如何工作? mov %%gs, %0 相反,GS的基础位于msr_gs_base中,并且电流可以像以下方式更换: /*0xb000 is the offset of per_cpu__current_task*/ cur_task = (unsigned long*)(x86_rdmsr64(MSR_GS_BASE) + 0xb000); println("cur_task:%p",*cur_task); 我的问题是: %GS指向GDT NULL的第一项!它的工作方式是从MSR_GS_BASE读取的,它是CPU功能?我需要一些引用. 解决方案 来自 amd Architemen ,第4.5.3节: FS和GS寄存器以64位模式.
10 2023-12-16
编程技术问答社区
可以使用" MOV DS,AX"来传输8位数据?
我正在研究作者-Godse的MP书. 我的问题: a)可以将AX,BX,CX,DX 16位寄存器用作传输" 8位"数据的来源? 例如:Mov [734AH],BX; bx to ds的副本"内容". 在这里,内容意味着什么? 数据或Word 只有字? ex2:Mov DS,BX;从bx到ds副本"单词". 他们为什么提到单词本身? (如果也可以传输1个字节数据,则它们本身将给出"内容".). 解决方案 a)可以将AX,BX,CX,DX 16位寄存器用作传输" 8位"数据的来源? 不完全是.但是,您可以使用AL作为传输8位数据的来源(特别是低阶8位AX). AX本身拥有16位,如果您将其用作A MOV指令的来源. ex:MOV [734AH],BX; BX至DS的"内容"副本.在这里,内容意味着什么? a)数据或单词b)只有单词? "目录"只是 - BX的内容.其16位的值.它们被转移到给定的内存地址. ex2:mov ds,bx
6 2023-12-16
编程技术问答社区
谁能帮助我解决分段和8086 intel'的微处理器?
我正在阅读有关英特尔8086的体系结构,但无法弄清有关细分的以下内容:我知道该细分寄存器分别指向段,并包含64kb长段的基本地址.但是谁计算,在哪个点设置了细分寄存器中的物理地址?另外,由于可以通过多个段来访问一个物理地址:偏移对和段可能重叠,因此您如何确定不会覆盖某些内容?我可以在哪里阅读有关此的更多信息? 解决方案 一般来说,汇编程序只能使用偏移地址来访问逻辑地址.例如查看此代码: start lea si,[hello] ; Load effective address of string mov word [ds:si+10],0 ; Zero-terminate string after 10th letter jmp $ ; Loop endlessly ; Fill rest of the segment with 0s times 65536-($-$$) db
4 2023-12-16
编程技术问答社区
从物理地址(x86)计算逻辑地址
据我所知,物理地址是通过将段地址(16位)移动4次并在16位偏移地址添加的情况下计算得出的. 我的问题是,如果两套不同的段:偏移地址值给出相同的结果,该怎么办 例如. 200A:B608和2138:A328 200a0 +B608 2B6A8 和 21380 +A328 2B6A8 都给出相同的结果!! 现在,这是否意味着他们指出相同的物理地址(如果是,如何?), 或物理地址是否不应以上述方式计算? 或,如果有效,那么如何从物理地址回到片段:偏移地址(可能吗?) 解决方案 在实地点模式下,段寄存器值确实是向左移动4位,然后添加到偏移量中以形成一个20位线性地址(在此模式下与物理地址相同). 显然,这意味着与不同的段:偏移对可以翻译成相同的物理地址(就像在启用分页的受保护模式下不同的线性地址可以转化为相同的物理地址).由于逻辑和线性地址之间没有1:1映射,您唯一可以从线性地址获得的东西是一组段:偏移对. 您可
10 2023-12-16
编程技术问答社区
物理地址公式以16位真实模式:为什么将段乘以16?
physical address=16*selector+offset 但是我不知道为什么将16乘以选择? 解决方案 为了与Z80成为"程序员兼容",但仍然能够使用超过64 KIB的内存,引入了早期的英特尔处理器内存分割.在添加到16位偏移量中之前,16位段将被移动4位(意味着乘法乘以16,而不是 64),从而产生了20位地址. 对于习惯于Z80的程序员来说,所需的只是使用OS提供的片段,并且他们可以根据自己的喜好使用给定的64千键偏移.新程序员可以对细分市场进行更复杂的操纵,从而使他们可以访问1个MIB地址空间(IBM PC将其降低至640 KIB,但出于他们自己的原因). > 其他解决方案 8088/8086的目标是提供一种手段,通过16位处理器可以具有1兆字节的地址空间,而无需程序员必须将地址空间分为64k的块,并担心地址是否地址.跨越了它们之间的边界.尽管它的损害很大,但实际上比我看到的任何其他方法都要使用超过寄存器大小的地址更好.如果将数据自然细分为6
12 2023-12-16
编程技术问答社区
从给定的物理地址和有效地址中找到分段地址
如何从给定数据找到段地址? 物理地址= 0x119b,有效地址= 0x10ab 公式是什么? 解决方案 x86 16位实际模式中的有效地址只是20位 段:offset 地址.您给出的问题是确定与有效地址合并时的段值0x10AB会产生0x119b的物理(线性)地址. 可以从段:Offset 配对的物理地址与公式physaddr=(segment
0 2023-12-16
编程技术问答社区
在一个将自己缝在自己尾巴上的程序中,如何在64KB的代码段中进行缠绕,无休止地进行缠绕?
如果指令的顺序执行通过偏移量65535,则 8086 将在同一代码段中从Offset 0获取下一个指令字节. Next .com程序使用此事实,并不断将其整个代码(总计32个字节)缝合到其自己的尾巴上,并在64KB代码段中缠绕.您可以将其称为二进制Quine . ORG 256 ; .COM programs start with CS=DS=ES=SS Begin: mov ax, cs ; 2 Providing an exterior stack add ax, 4096 ; 3 mov ss, ax ; 2 mov sp, 256 ; 3 cli ; 1 call Next ; 3 This gets encoded with a relative offset Next: p
2 2023-12-16
编程技术问答社区
在ORG指令后设置段寄存器
我目前正在关注有关OS开发的教程,其中包括有关引导程序的讨论. 我的引导加载程序当前处于16位实际模式,因此,我可以使用所提供的BIOS中断(例如VGA视频中断等). BIOS提供视频中断0x10(即视频电视输出).视频中断具有函数0x0E,它使我可以在屏幕上打印一个字符. 这是此基本引导加载程序: org 0x7c00 ; Set program start (origin) address location at 0x7c00. ; This program is loaded by the BIOS at 0x7c00. bits 16 ; We live in 16-bit Real Mode. start: jmp loader bootmsg db "Welcome to my Op
2 2023-12-16
编程技术问答社区