您的位置:首页 > 其它

汇编语言的Hello world程序

2013-07-08 13:01 483 查看
    最近一直在学习汇编语言,但是只学会做了一些最基本的程序,都没有输出,只是把结果储存在一个通用寄存器里然后结束,这样怎么行?确实,可以通过Windows自带的Debug程序来单步执行程序以观察结果,但是这是不够的,不够简便,不能直接双击执行程序。于是,今天早上我决定试验一下汇编语言的Hello world程序,现在试验成功了,我就来和大家分享一下这个程序,顺便拿点积分。但是请注意,阅读前请先搞懂一些基础知识,比如mov指令,通用寄存器和段寄存器。不然无论我怎么努力讲解,你都听不懂的。

    首先,我们先来看一下源程序。

assume cs:code,ds:data

data segment
db 'Hello world!',10,13,'$'
data ends

code segment
start:
mov ax,data
mov ds,ax
mov dx,0

mov ax,0900H
int 21H

mov ax,0100H
int 21H

mov ax,4C00H
int 21H
code ends
end start


    整个程序不是很长,翻译成机器码后只有27个字节。下面我们来逐行解释一下。

    第一行,我们看到了伪指令 assume cs:code,ds:data ,这是在告诉汇编语言的编译器,我们要把我们定义的code段和data段与段寄存器cs和ds挂钩。cs存放代码,ds存放数据,大家应该都清楚吧?其实,在这里,code和data只是标识符,你可以取任何你喜欢的名字,比如我也可以把它叫做DYProProgramStudio段。其实DYProProgramStudio就是我工作的程序工作室的名字。。。

    第二行和第四行的伪指令segment和end是告诉编译器,这个段在何处开始,何处结束,学过高级语言的人应该知道,它们就类似于C/C++系语言里面的{},虽然不完全一样。

    看一下第三行,伪指令db让编译器为我们申请一些存放字节型数据的内存空间(它的意思是define byte,同样的定义字形数据的就是dw,define word),这里我们用这些空间存放字符串。字符串是用单引号括起来括起来的字符,可以随便改,改成 I love DYPro! 也没有关系。那个10和13,其实是ASCII码,就是换行的意思。类似于C、Java等语言里面的 \n 和 \r 。总之就是用来换行的。如果你喜欢十六进制,写成 0AH 和 0DH 也可以,只要记住,数据不能以字母开头,必须补上一个0才行。那个美元号,是字符串结束的标志,类似于
\0 。

    第二个段才是我们的代码段。那里才放着我们的代码。好,先看一下,那个“start:”被称做程序的入口地址,CPU会从这个地址开始执行程序。同样的,start也只是一个标示符。其实标号可以有很多,决定哪个是入口地址的其实是最后一行的伪指令end,end后面跟的标号就被编译器认为是程序的入口地址了。

    好,终于到了研究代码的时间了!先看一下前两条代码,mov ax,data 和 mov ds,ax 。其实这两条代码指的是将ds与data段联系上。data因为只是个标识符,所以在程序运行时会被一个具体的段地址取代。而且因为ds是段寄存器,所起不能直接通过mov指令传输地址,要通过通用寄存器来中转一下。这里我们使用ax。

    第三条语句mov dx,0的作用是将通用寄存器dx的值清零,这是为了和下文的int 21H配合,在输出字符串时,dx是用作ds的偏移地址的。

    我们看一下mov ax,0900H和int 32H这两条语句。他们其实是使用了DOS的中断机制。中断其实有点类似于过程,函数和方法。int 21H 调用了21号中断,21号中断会自动读取ah寄存器的值(这里是09),并进行相应的操作。当ah为09时,int 21H的操作是:从段地址为ds,偏移地址为dx的地址起,不停输出字符,直到碰到美元号(所以我还没找到办法输出美元号本身,用ASCII码表示的方法也是无效的)。

   下面的第二个int 21H得到的ah的值是01,意思是读取一个字符,ASCII码存放在al中。这个输入是有显示的,而且没有机会按退格键的。在这里我们其实不需要这个字符,只是让用户有机会观察一下,按下任意键再使程序退出。但是我在实验的时候发现:如果不加这个中断,exe文件中就不会输出字符串,即使是用cmd运行,也没有输出,但是用Debug调试的时候,只要用p命令执行中断,就有输出,尚未搞清楚这是为什么。不管,加上就行。

    第三个终端,ah表示4C,此时中断的作用是结束程序,把控制权交还给调用它的程序(操作系统,cmd,debug等),注意,这个中断会提取al的值,这个值可以说是程序的返回值,或错误码。比如 mov ax,4C01 ,再 int 21H 就说明程序是因为错误而退出,错误码是1。这个跟C++里的主函数的return 0,return 1差不多。

    好,既然代码我们说明完了,我们来讲一下如何编译。作者我,JerryYangOnly,使用的是微软的MASM编译器的5.0版本。这个版本其实也够用。但是这个版本貌似没有一键完成的ML.EXE,所以我决定,自己写一个Python程序实现这个功能。代码如下。

import os
fname = input("Input file name: ")
os.system("masm " + fname + ".asm;")
os.system("link " + fname + ".obj;")


    很简单,但是够了。这个小程序我就不多讲了,有机会的话我会开一个Python的教程坑,大家到时候再看吧。也有可能开Pascal,C/C++,Java的,到时候看着办吧。反正把这段代码复制下来,写进 ****.py 里面,就成了。装好Python的人就可以双击,输入文件名(不需要扩展名),就自动编译了。如果你想看看编译的结果,就试试用cmd输入命令“python 文件名.py”或者直接“文件名.py”。连接的时候会提示你没有栈段(No stack segment),不用理他,照样会通过,因为这个只是提醒(warning直译的话是警告)。其实你也可以通过命令行调用MASM.EXE和LINK.EXE两个程序,只不过比较麻烦罢了。命令行代码也可以写进bat批处理文件里面,可以起到和py脚本文件一样的效果。
    至此,我们的程序就大功告成了!双击运行你连接出来的.exe文件,看看,是不是很有成就感?汇编的Hello world耶!下次可以和朋友炫耀一下,很拽地说一句“给你们源文件你们都看不懂!”,多风光!

    好了,大家下次再见!记住,转载的时候加上一句,“原作者:来自DYPro Program Studio的Jerry Yang!(本文是转的)”,谢谢合作!(我都帮你写好了,粘贴一下又不会死,对吧?)拜拜!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息