因此,我开始开发x86\u 64 hobby内核,我发现这段代码用于加载GDT(全局描述符表),但我不知道它是做什么的。
load_gdt:
lgdt [rdi]
mov ax, 0x10
mov ss, ax
mov ds, ax
mov es, ax
mov rax, qword .trampoline
push qword 0x8
push rax
o64 retf
.trampoline:
ret
我知道它从rdi寄存器(sysv abi中函数调用的第一个参数的寄存器)加载我的gdt描述符,但我不知道为什么我需要将所有段寄存器设置为0x10,其余的是什么黑魔法?
一旦(新的)GDT存在,接下来要做的就是将段regs设置为索引GDT的选择器;这就是为什么你首先想要GDT。或者,如果您正在更换旧的GDT,则需要您自己的GDT,例如UEFI的GDT。(由于您已经处于64位模式,因此必须已经有GDT;mov-rax,.trampoline与RIP-relative-LEA相比是一个奇怪的选择,但包含REX前缀,因此在32位模式下解码错误。)
最后几位是通过推一个新的CS:RIP并做一个far-ret将其弹出到CS:RIP中来设置CS的跳远。它需要是64位操作数大小,以确保从堆栈中弹出64位RIP,而不是32位EIP。
(当然,您不能将mov转换为CS;这将是一个跳转,因为它会改变代码提取的来源。x86只允许通过call/jmp或retf等跳转指令编写E/RIP或CS:E/RIP。)
参见https://wiki.osdev.org/Global_Descriptor_Table
该程序应该使用int 0x10在ASCII中打印一个具有给定字符的金字塔,3行的预期结果(下面代码中使用的数量)将是: A. a a a a a 要编译和运行代码,我使用nasm编译它,然后使用qemu进行仿真: 然而,程序get无法打印所有ASCII值。此外,如果有任何针对nasm代码的调试器,可以让您逐行运行,允许您检查寄存器值,这对学习也很有帮助。
我知道这行代码将某些内容移动到eax寄存器中,但是dword ptr [edx 15Ch]有什么作用? 它是否接受edx中的值并添加15C=Q,然后将地址Q中的值加载到eax中?如果是这样,这个conetxt中的dword ptr是什么意思?
问题内容: 这是我的代码: 当运行它输出。我究竟做错了什么? 问题答案: 您正在调用一个没有隐式字符串表示形式的实际数组。 为了输出数组的内容,你可以使用,或功能或自定义输出,你可以使用,甚至是循环:
在方法或类范围内,下面的行编译(带有警告): 在类作用域中,变量获取其默认值,以下给出未定义引用错误: 这难道不是第一个应该以相同的未定义引用错误结束吗?或者第二行应该编译?或者我错过了什么?
问题内容: 因此,我刚刚意识到反编译Java代码是多么容易。我一直在网上搜索,但似乎无法弄清楚 为什么 这么容易。每次我在Google上搜索“为什么要反编译文件?”之类的信息时,或“为什么Java这么容易反编译”,我所得到的只是指向可以轻松反编译我的代码的软件的链接。因此,我向您介绍StackOverflow:为什么Java可以转换回容易阅读的源代码,而C ++和其他语言对反编译不是很友好? 谢谢
奇怪的是,标记为“OK”的行编译得很好,但标记为“Error”的行失败了。它们看起来基本上是一样的。