7 当心寄存器(harib17g)

hello.hrb的大小现在是21个字节,能不能再让它变小点呢?我们做了如下修改,用了一个循环。

本次的hello.nas

  1. [INSTRSET "i486p"]
  2. [BITS 32]
  3. MOV ECX,msg
  4. putloop:
  5. MOV AL,[CS:ECX]
  6. CMP AL,0
  7. JE fin
  8. INT 0x40
  9. ADD ECX,1
  10. JMP putloop
  11. fin:
  12. RETF
  13. msg:
  14. DB "hello",0

改成这样后make一下,hello.hrb变成了26个字节,居然还大了5个字节,哎,好失望。不过,这样改也有好处,即便以后要显示很长的字符串,程序也不会变得太大。

马上运行一下看看。

7 当心寄存器(harib17g) - 图1

哎呀?

咦?为啥只显示出一个h呢?再把hello.nas仔细检查一遍,也没发现什么不对劲的地方啊……

■■■■■

既然应用程序没问题,那问题肯定出在操作系统身上。不过,到底是哪里有问题呢?刚刚找到了点眉目,我们给_asm_cons_putchar添上2行代码,就是PUSHAD和POPAD。

本次的naskfunc.nas节选

  1. _asm_cons_putchar:
  2. STI
  3. PUSHAD ; 这里!
  4. PUSH 1
  5. AND EAX,0xff ; AHEAX的高位置0,将EAX置为已存入字符编码的状态
  6. PUSH EAX
  7. PUSH DWORD [0x0fec] ; 读取内存并PUSH该值
  8. CALL _cons_putchar
  9. ADD ESP,12 ; 将栈中的数据丢弃
  10. POPAD ; 这里!
  11. IRETD

为什么要这么改我们待会儿再讲,先来试验一下哦。

7 当心寄存器(harib17g) - 图2

哦,好了!

果然是这个问题呀。那为什么会想到加上PUSHAD和POPAD呢?因为笔者推测这有可能是INT 0x40之后ECX寄存器的值发生了变化所导致的,应该是_cons_putchar改动了ECX的值。因此,我们加上了PUSHAD和POPAD确保可以将全部寄存器的值还原,这样程序就能正常运行了。