Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly IA32基本用法_Assembly_Kernel_X86 64 - Fatal编程技术网

Assembly IA32基本用法

Assembly IA32基本用法,assembly,kernel,x86-64,Assembly,Kernel,X86 64,我正在尝试编写一个自定义内核,该内核使用%gs作为段基来加载和存储x86_64下的CPU本地信息。(我正在使用QEMU 2.1.0来运行我的内核,如果有必要的话。),但从那以后我发现了更多的信息,而这些变化并不完全符合我前面的问题 我正在使用IA32\u GS\u BASEMSR加载CPU本地数据结构的地址。然而,无论我做什么,MSR中的地址似乎都没有得到尊重%gs的计算结果仍然为零,因此我得到的地址(a)在使用时崩溃,(b)不指向我以前加载的数据结构 我有两个假设。一个是我需要在MSR值被确认

我正在尝试编写一个自定义内核,该内核使用
%gs
作为段基来加载和存储x86_64下的CPU本地信息。(我正在使用QEMU 2.1.0来运行我的内核,如果有必要的话。),但从那以后我发现了更多的信息,而这些变化并不完全符合我前面的问题

我正在使用
IA32\u GS\u BASE
MSR加载CPU本地数据结构的地址。然而,无论我做什么,MSR中的地址似乎都没有得到尊重<代码>%gs的计算结果仍然为零,因此我得到的地址(a)在使用时崩溃,(b)不指向我以前加载的数据结构

我有两个假设。一个是我需要在MSR值被确认之前执行某种缓存刷新操作。另一个原因是我没有正确设置MSR。然而,
IA32_GS_BASE
的文档记录非常糟糕,我找不到任何证据支持这两种理论


有什么建议吗?(没有双关语。)

一些快速搜索表明,更好的选择是使用该指令。这避免了MSR的任何混乱


如果这不起作用,另一种选择是设置
IA32_KERNEL\u GS_BASE
(索引0xC0000102;注意中间的
KERNEL
),然后是指令。

根据我的测试,您的问题不在于
GS
BASE。 在qemu中运行会导致双重故障,这不会提供任何关于
GS
问题的指示。使用bochs运行时,我没有从代码中获得任何合理的调试输出,但我可以使用内置调试器来证明至少
GS
base的设置和读取操作是有效的

(0) [0x000000000030d346] 0008:ffffff800030d346 (unk. ctxt): wrmsr                     ; 0f30
<bochs:20> r
rax: 0x00000000_00828c00 rcx: 0x00000000_c0000101
rdx: 0x00000000_ffffff80 rbx: 0xffffff80_00833480
rsp: 0xffffff80_0010bfb0 rbp: 0xffffff80_0010bfb0
rsi: 0xffffff80_0010bf48 rdi: 0xffffff80_00828c00
r8 : 0xffffff80_007dbe03 r9 : 0x00000000_0000007f
r10: 0x00000021_00000000 r11: 0xffffff80_00cf9000
r12: 0x80000000_00c74003 r13: 0x00000000_00000084
r14: 0x00000000_00a33000 r15: 0xffffff80_00c75000
rip: 0xffffff80_0030d346
eflags 0x00000002: id vip vif ac vm rf nt IOPL=0 of df if tf sf zf af pf cf
我在随后使用的
GS
中放置了另一个断点,不确定这在源代码中的位置:

(0) [0x00000000003232b2] 0008:ffffff80003232b2 (unk. ctxt): mov r14d, dword ptr gs:0x000000000000001c ; 65448b34251c000000
好的,所以它读作
gs:0x1c
。测试表明这是零。为了证明该值确实是从正确的内存位置读取的,让我们将其设置为有趣的值:

<bochs:21> page 0xffffff8000828c1c
PML4: 0x0000000000c72023 ps         A pcd pwt S W P
PDPE: 0x0000000000c6e023 ps         A pcd pwt S W P
 PDE: 0x0000000000a7e023 ps         A pcd pwt S W P
 PTE: 0x0000000000828063    g pat D A pcd pwt S W P
linear page 0xffffff8000828000 maps to physical page 0x0000000000828000
<bochs:22> setpmem 0x828c1c 4 0x42424242
第0xFFFF8000828C1C页
PML4:0x0000000000c72023 ps A pcd pwt S W P
PDPE:0x0000000000c6e023 ps A pcd pwt S W P
PDE:0x0000000000a7e023 ps A pcd pwt S W P
私人股本:0x0000000000828063 g帕特D A pcd pwt S W P
线性页面0xFFFF8000828000映射到物理页面0x0000000000828000
setpmem 0x828c1c 4 0x4242
然后,加载将毫无问题地执行,并确实加载该值:

<bochs:23> s
Next at t=91228625505
(0) [0x00000000003232bb] 0008:ffffff80003232bb (unk. ctxt): lea rdi, qword ptr ds:[rip+5863966] ; 488d3d1e7a5900
<bochs:24> r
rax: 0x00000000_00000000 rcx: 0xffffff80_0087ae80
rdx: 0xffffff80_008bad10 rbx: 0xffffff80_0075b564
rsp: 0xffffff80_0010bde0 rbp: 0xffffff80_0010be10
rsi: 0x00000000_00000072 rdi: 0xffffff80_0075b564
r8 : 0x00000000_00000010 r9 : 0x00000000_00000000
r10: 0x00000000_00000000 r11: 0x00000000_00000000
r12: 0xffffff80_0010bec4 r13: 0x00000000_00000084
r14: 0x00000000_42424242 r15: 0xffffff80_008f2b38
rip: 0xffffff80_003232bb
eflags 0x00000082: id vip vif ac vm rf nt IOPL=0 of df if tf SF zf af pf cf
s
下一个在t=91228625505
(0)[0x00000000003232bb]0008:ffffff80003232bb(unk.ctxt):LEARDI,qword ptr ds:[rip+5863966];488d3d1e7a5900
R
rax:0x00000000\u00000000 rcx:0xffffff80\u 0087ae80
rdx:0xFFFF80_00810 rbx:0xffffff80_0075b564
rsp:0xFFFF80_0010bde0 rbp:0xffffff80_0010be10
rsi:0x00000000\u00000072 rdi:0xffffff80\u 0075b564
r8:0x00000000\u00000010 r9:0x00000000\u00000000
r10:0x00000000\u00000000 r11:0x00000000\u00000000
r12:0xFFFF80\u 0010bec4 r13:0x00000000\u00000084
r14:0x00000000_424242 r15:0xffffff80_008f2b38
rip:0xFFFF80_003232bb
eflags 0x00000082:id vip vif ac vm rf nt IOPL=0如果tf SF zf af cf

不管你的问题是什么,它可能在别处。

wrgsbase
不起作用;它所做的只是使处理器出现三重故障。另外,
IA32_KERNEL_GS_BASE
也在设置中,但据我所知,它在切换到用户模式之前不会做任何事情。更正:
IA32_KERNEL_GS_BASE
在用户模式之前不会被使用;它仍然可以设置为内核模式。@wjk查看我提供的链接,
SWAPGS
需要内核模式-因此,
IA32\u kernel\u GS\u BASE
将通过
SWAPGS
与当前的GS BASE交换。您可以在AMD的文档中找到更多关于此MSR的文档,其原始名称为
MSR\u GS\u BASE
。在加载gs base之前,您是否尝试过使用空选择器(0)加载
%gs
?描述符缓存中可能仍有过时的限制或属性。@RossRidge-任何直接设置
%gs
都会导致三重错误。我认为这是因为将段直接设置在x86_64下是无效的。此外,请详细说明“过时限制或属性”。将
%gs
设置为零不会导致故障。在内核和用户模式下,以长模式加载段寄存器也是完全合法的。在所有模式下,每个段寄存器都由描述符缓存支持,该缓存保存最后加载的描述符的值。它有基础、限制和各种属性。切换处理器模式不会改变描述符缓存,因此GS描述符缓存可能仍然有限制,并且具有来自实模式的属性。在长模式下应该忽略它们,但这可能假设GS在长模式下实际加载了一次。@RossRidge-
%GS
被归零了一次。据我所知,从那以后就再也没有人碰过它。好吧,在您链接的代码中进入长模式后,它被更改了,因此它似乎排除了描述符缓存中的旧值。
<bochs:23> s
Next at t=91228625505
(0) [0x00000000003232bb] 0008:ffffff80003232bb (unk. ctxt): lea rdi, qword ptr ds:[rip+5863966] ; 488d3d1e7a5900
<bochs:24> r
rax: 0x00000000_00000000 rcx: 0xffffff80_0087ae80
rdx: 0xffffff80_008bad10 rbx: 0xffffff80_0075b564
rsp: 0xffffff80_0010bde0 rbp: 0xffffff80_0010be10
rsi: 0x00000000_00000072 rdi: 0xffffff80_0075b564
r8 : 0x00000000_00000010 r9 : 0x00000000_00000000
r10: 0x00000000_00000000 r11: 0x00000000_00000000
r12: 0xffffff80_0010bec4 r13: 0x00000000_00000084
r14: 0x00000000_42424242 r15: 0xffffff80_008f2b38
rip: 0xffffff80_003232bb
eflags 0x00000082: id vip vif ac vm rf nt IOPL=0 of df if tf SF zf af pf cf