请注意,本文编写于 1632 天前,最后修改于 1632 天前,其中某些信息可能已经过时。
开门见山的说,我上次这道题留下了很多的疑问,今天我就来填坑啦(我居然会填坑伟大的医学奇迹!)。我们这次准备分三个步骤来好好的探究一下16位程序。
其实在基本的图像界面,是无法直观的区分16,32与64位程序的。我们是在计算机组成原理这门课中接触位数的概念的,他们在汇编里面最明显的去别就是使用的寄存器不同。但是我们在看不到汇编语句之前,我们是否有方法区分16,32,64位程序呢。答案是肯定的,我们可以使用Winhex来观察这三个程序。
首先我们先来观察32位与64位的程序,很明显这两个程序大体的头部是相同的,有DOS头和PE头。而区分他们位数的关键就在PE头的头部,仔细观察,第一张图为64位程序的头部,第二张为32位程序的头部。他们分别为【50 45 00 00 64 86】(64位程序),【50 45 00 00 4C 01】(32位程序)。通常这里会决定一个程序的位数,但是使用winhex将两个程序的标志位进行了互换,两个程序全部无法运行,并且32位的IDA也无法打开32位的程序,提示应该使用64位的IDA进行反编译。对于我们的16位程序,winhex打开后是没有PE头的,只有一个MZ开头的魔术头。
答案是不能,但是DOS可以。之里面就要纠正我的一个错误概念,我一直以为win10下的cmd(命令提示符)就是我们所谓的DOS。我们在windows操作系统里进的DOS(即输入 CMD 进命令提示符)不是纯DOS,只是为方便某些需求而建立的,而纯DOS本身就是一种操作系统。简单的打个比方:你可以在纯DOS下删除你的windows系统,但在你所说的"命令提示符"里却不能,因为你不可能"在房子里面拆房子吧?") dos是磁盘操作系统;命令提示符是dos系统的界面中输入dos命令的提示位置;cmd是win10系统运行其自带dos的命令。
所以在win10系统下,并不存在DOS系统,只是一个像DOS一样的cmd程序。而在这个cmd中我们是无法运行我们的16位程序的,而32位与64位程序都可以正常运行。
那么我们应该如何运行16位的程序呢,我们这里需要用到一个沙盒(DOSbox),DOSBox 是一个 DOS 模拟程序,由于它采用的是 SDL 库,所以可以很方便的移植到其他的平台。DOSBox的最新版本已经支持在 Windows、Linux、Mac OS X、BeOS 、palmOS、Android 、webOS、os/2等系统中运行。很不巧,我找的16位的程序是一个纯算法的exe,没有输入没有输出,我们无法知道这个程序是否已经运行。在我苦苦的寻觅下,我决定自己写一个16位的“Hello World”。我们可以直接使用记事本将我们的代码写下来,之后在进行编译与link。
stack segment stack 'stack'
dw 32 dup(0)
stack ends
data segment
hello db"hello,world!$" ;定义字符串常量hello
data ends
code segment
assume ds:data,cs:code
start: push ds
mov ax,0
push ax
mov ax,data
mov ds,ax
lea dx,hello ;取字符串常量hello的偏移地址,送入dx
mov ah,9 ;9号功能调用:在屏幕上显示字符串常量hello的值
int 21h
retf
code ends
end start
但是编译与链接我们应该怎么实现,我们之前使用的VS等工具只需要用一个按钮就可以实现。换句话说编译链接对于我们来说是透明的。这里不多bb,直接上图。
masm.exe是一个编译程序,编译完成后会生成一个Obj文件。而我们的link.exe是链接文件,链接obj生成一个exe文件。(这个地方C++曾经讲过,但是我没认真听,导致我研究了好久)。这里我在网上找到了一个更加nb的软件,类似我们的vs只不过是直接写汇编的,编译链接也是透明的十分方便,我就放在附件里面了。如果想要享受手操的快感,可以找到这个软件对应的DOSbox,进行自己的手操模拟,masm.exe与link.exe在软件中都有,有兴趣的话可以单独自己研究研究。
最后我们的16位程序就可以运行啦!至于有没有其他的方法,之后碰见在研究吧!
全部评论 (暂无评论)
info 还没有任何评论,你来说两句呐!