如何在不添加 a或 的情况下添加a SS:orES:使用 AT&T 汇编语法?.byte 0x36.byte 0x26
IE。我如何能够在mov dword ptr ss:[esp+0x10], offset foo不使用以下内容的情况下从 Intel 语法转换为 AT&T:
.byte 0x36
movl $foo, 0x10(%esp)
Run Code Online (Sandbox Code Playgroud)
我试过movl $foo, %ss:0x10(%esp)在没有警告的情况下组装,但是,通过二进制文件,仍然没有添加SS:
我发现一个常量的文字get放在程序的数据段中(来自SO)并且是只读的,因此行"s [0] ='a'"会导致错误,这实际上发生在我取消注释该行并运行.但是,当我查看MS VS中的内存窗口时,变量全部放在内存中.我很好奇他们(编译器)如何强制执行对's'的只读访问?
#include <iostream>
int main(void)
{
char *s = "1023";
char s_arr[] = "4237";
char *d = "5067";
char s_arr_1[] = "9999";
char *e = "6789";
printf("%c\n", s[0]);
// s[0] = 'a'; This line would error out since s should point to data segment of the program
printf("%s\n", s);
system ("pause");
}
0x002E54F4 31 30 32 33 00 00 00 00 34 32 33 37 00 00 00 00 1023....4237....
0x002E5504 35 30 36 37 00 00 …Run Code Online (Sandbox Code Playgroud) 在Linux内核以及在线的许多x86教程中,我看到人们建议使用两个代码段和两个数据段.我理解需要两个代码段,因为CPL需要与DPL完全匹配(对于不符合的段).
但是,这些教程中没有一个(也没有任何关于StackOverflow的相关问题),具体说明为什么我们需要两个数据段.这些工作与代码段不同,因为CPL = 0的进程可以访问DPL = 3的数据段.
如果我们在不同权限级别的进程之间切换,则具有两个数据段的缺点是必须重新加载DS,ES等寄存器.
所以我的具体问题是:鉴于我们使用的是平面内存模型,所有代码和段完全重叠,它的用途和内核数据段的用途是什么,而不仅仅是一个用户数据段?
x86 operating-system kernel linux-kernel memory-segmentation
我注意到我正在编写的一些代码中存在潜在的错误。
我认为,如果我使用mov ax, seg segment_name,该程序可能是不可移植的,并且只能在特定配置的一台机器上运行,因为加载位置可能因机器而异。
所以我决定在两台运行 DOS 的不同机器上反汇编一个只包含一条指令的程序,我发现问题神奇地解决了。
一号机上的调试输出:0C7A:014C B8BB0C MOV AX,0CBB
二号机器上的调试输出:06CA:014C B80B07 MOV AX,070B
十六进制转储程序后,我发现未更改的字节实际上是B84200.
手动将这些字节插入到程序中会导致mov ax, 0042
那么 PE 格式是否存储对这些指令的引用并在运行时更新它们?
dos relocation portable-executable memory-segmentation x86-16
在GDT 上的文章中, OSDev wiki 描述了用作 CS 描述符的 D 位的标志如下:
Sz:大小位。如果为0,则选择器定义 16 位保护模式。如果为1,则定义 32 位保护模式。您可以同时拥有 16 位和 32 位选择器。
另一个问题引用了 Intel 手册:代码段描述符中的 D 标志对 x86-64 指令有什么作用?它链接到Intel 64 和 IA-32 架构软件开发人员手册第 3 卷 [...]:系统编程指南中的“3.4.5 段描述符”部分 ,阅读:
D/B(默认操作大小/默认堆栈指针大小和/或上限)标志
根据段描述符是可执行代码段、向下扩展数据段还是堆栈段执行不同的功能。(对于 32 位代码和数据段,此标志应始终设置为 1,对于 16 位代码和数据段,应始终设置为 0。)
• 可执行代码段。该标志称为 D 标志,它表示段中指令引用的有效地址和操作数的默认长度。如果设置了标志,则假定为 32 位地址和 32 位或 8 位操作数;如果清楚,则假定为 16 位地址和 16 位或 8 位操作数。指令前缀 66H 可用于选择默认值以外的操作数大小,前缀 67H 可用于选择默认值以外的地址大小。
问题是,“D”代表什么?
我正在研究 .EXE 程序和 .COM 程序之间的区别。.EXE 对我来说是合乎逻辑的,堆栈位于相对于程序代码的另一个段中(实际上堆栈是强制的并用 .STACK 指示此限制),因此,当我去插入值时??堆栈(在 .EXE 中),使用与程序不同的段,我不会混淆这两者。
例子:
SP = 0400
SS = 3996 CS = 3995 IP = 0000
Run Code Online (Sandbox Code Playgroud)
栈的容量为1024 Byte(400h),指的是栈段3996h,不同于代码段3995h。所以我确信数据不会混淆。
我不明白的是什么时候我必须处理 .COM 程序;因为我很清楚他们只使用一个段,我发现自己遇到了类似的情况:
SP = FFEE
SS = 114A CS = 114A IP = 0100
Run Code Online (Sandbox Code Playgroud)
我有与代码段匹配的堆栈段。因此,如果我继续将值放入堆栈中,它们迟早会出现在我的代码中吗?
我正在研究一些反反汇编技术,并发现了以下片段:
push 0x33
call $+5
add [esp+0x10+var_10], 5
retf
; next instruction here
Run Code Online (Sandbox Code Playgroud)
简而言之,这会立即跳转到 后面的指令RETF,但会弄乱 32 位反汇编程序。我仍然不清楚为什么会这样。
现在,我被告知RETF返回到 64 位段,因此在 32 位调试器上调试它会产生错误的反汇编。当在 64 位调试器(在我的例子中是 Windbg)上运行此代码片段时,它会产生正确的结果。
我的问题是:有什么特别的吗push 0x33?0x33 是某种特殊值吗?
IAPX88 可以处理 1 兆字节内存(20 位寻址),现在我的问题是我们如何使用两个 16 位寄存器来制作 20 位地址。请举例说明。
我有点困惑,我从许多不同的网站上阅读,但我不清楚:
每个段寄存器都有可见部分和不可见部分。可见部分称为段选择器,并且有直接指令来加载段选择器。
请求者特权级别(RPL):该字段标识提供受保护的数据访问的特权级别。
好的,我知道我可以在汇编中使用指令,例如加载选择器,但我无法修改 RPL,对吧?它从何而来?CPU是如何选择的呢?谢谢
我已经编写了一个代码,它应该生成某种数字列表,但是即使我确实为它们分配了初始值,我的数据段变量也没有被初始化?
这是我的代码,但数据段只保留垃圾值:
MODEL small
STACK 100h
DATA SEGMENT
size1 dw 0000h
arr dw 20 dup(0000h)
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
sidra_rekursivit proc
mov bp, sp
xor ax, ax
mov ax, [bp+2]
; tnai azira
cmp ax, 1
je azira
; tempo
mov cx, ax ; save ax
shr ax, 1
jnc zugi ; if zugi
izugi: ; else
mov ax, cx
;multiply by 3
shl ax, 1
add ax, cx
;end multiply
; add 1 …Run Code Online (Sandbox Code Playgroud) assembly ×7
x86 ×5
x86-16 ×4
dos ×3
att ×1
c++ ×1
gdt ×1
kernel ×1
linux-kernel ×1
osdev ×1
privileges ×1
real-mode ×1
relocation ×1
terminology ×1
x86-64 ×1