Archive for the ‘语言’ Category

GetNtdllBaseAddress

GetNtdllBaseAddress.cpp

pushad

pushad将8个32位的通用寄存器入栈,入栈顺序为eax、ecx、edx、ebx、esp、ebp、esi、edi。pusha是16位版的。

天书夜读2.2思考与练习

int a, b, d;
d = a + b;
int i = 1, c = 0;
while(c < 0x64)
{
	c += i;
}
switch(c)
{
	case 0:
		d = 1;
	case 1:
		d = c;
		break;
	default:
		d = 0;
}
return d;

0xCC

经常在debug模式下看到有如下汇编代码用0xCC填充栈空间:

mov ecx, 30h

mov eax, 0CCCCCCCCh

rep stos dword ptr es:[edi]

今天才知道0xCC是int 3调试中断的机器码,恍然大悟。

浅淡对assume和org的理解

MASM中有些伪指令还真是不好理解,这里谈谈我对assume和org的一点理解。如有误,还请各位告知。

伪指令很好理解,就是无法将它们汇编成对应的机器指令。这里的assume和org也是如此,它们所影响的是编译时地址偏移的计算。

众所周知,内存的访问由内存地址决定。编译后的程序运行时具体被加载到哪是不得而知的,重定位可以通过程序被加载的基址+程序内偏移来确定,因此程序内偏移的确定就尤为重要了。

Intel系列CPU访问内存采用的是段式结构,因此无论是代码还是数据,其内存地址都需要指明段地址和段内偏移,访问时就需要一个段寄存器+一个段内偏移了。assume的作用就体现在这了,比如你在data segment中定义了一个变量var dd 0,而在代码中的访问方式如mov eax, var,由于没有指明段寄存器因此汇编器在编译时就需要计算出var的内存地址。如何计算?汇编中数据寻址默认是使用的ds段寄存器,因此只需确定var在ds段寄存器指明的段的段内偏移即可。如果没有assume伪指令,很明显,第一ds本身指向段地址在哪无法确定,第二就更别提var在ds的段内偏移了。

有了assume就不一样了,它解决了第二个问题。assume翻译过来为“假设”,assume ds: data就是假设ds指向的是data segment,而var在data segment中的偏移是可以确定的,如此var的段内偏移就确定了。但是assume还没能解决第一个问题,正如assume的翻译为“假设”一样,如果ds没有真的指向data segment,那么var的地址是ds:var在data segment中的偏移,必然是错误的。因此,实际上还需要在代码里手动mov ax, data; mov ds, ax;来让ds真正的指向data segment。

var定义在data segment中,那么var在data segment中的偏移是怎么出来的呢?这是因为MASM汇编器中有个“location counter”,由它来指示指令、数据在程序中的偏移,而org伪指令就是修改location counter的初值的。因此在程序中使用org后会使地址的计算要加上这个org值。

无觅相关文章插件,快速提升流量