第一个x86汇编程序
我们在学习每一门编程语言时都会习惯性地吧helloworld作为第一个程序,汇编也不例外,然而,博主却遇到了一个小小的难题,并在同学的帮助下解决,现写随笔做记录。
原hello.asm程序代码
data segment string db ;hello,assembly!',0dh,0ah,24h data ends code segment assume cs:code,ds:data start: mov bx,offset string mov di,00 again: mov dl,[bx+di] cmp dl,'$' jz done mov ah,02h int 21h inc di jmp again done: mov ah,4ch int 21h code ends end start
这个代码在使用MASM编译和链接的时候都是一切正常的,然而在真正执行时,出现了一堆乱码。
我很郁闷,于是在学习群里问大佬,大佬回答道:你试试这样:
在start:下面紧跟着写一个
mov ax,data
mov ds,ax
于是代码变成了这样
更改后的hello.asm 代码
data segment string db ;hello,assembly!',0dh,0ah,24h data ends code segment assume cs:code,ds:data start: mov ax,data mov ds,ax mov bx,offset string mov di,00 again: mov dl,[bx+di] cmp dl,'$' jz done mov ah,02h int 21h inc di jmp again done: mov ah,4ch int 21h code ends end start
上图中标红加粗的就是改的地方了,这里是把数据段段的地址位置data的值赋给了数据段寄存器ds
看似很简单的一个mov 操作
但是ds的地址就被改成了当前设置的data
所以才不会出现之前的乱码
我猜想原因应该是:
未进行mov ax,data mov ds,ax 赋值之前,ds的值是0,而data的段地址并不是0
只有在赋值后,ds和data才能统一,通过ds来访问数据段才能得到正确的结果
这里提及了两个概念,即代码段和代码段寄存器
首先是段的概念
我们编写的程序分为3个段
堆栈段stack segment
数据段data segment
代码段code segment
这三个段中,只有code segment是必须的
所以,在我写的helloworld程序中,我只用了data和code两个段
data段我用来存放数据
code段是具体的x86汇编代码
段寄存器是什么
The 6 Segment Registers are:
- Stack Segment (SS). Pointer to the stack.
- Code Segment (CS). Pointer to the code.
- Data Segment (DS). Pointer to the data.
- Extra Segment (ES). Pointer to extra data ('E' stands for 'Extra').
- F Segment (FS). Pointer to more extra data ('F' comes after 'E').
- G Segment (GS). Pointer to still more extra data ('G' comes after 'F').
参考自X86 Assembly/X86 Architecture - Wikibooks, open books for an open world
上面引用的资料表明,data segment段寄存器是一个指向数据段的指针
哦,指针
想必同学们会大吃一惊,
指针不初始化,结果就是乱码,这个应该就好理解多了吧。
所以,用mov ax,data mov ds,ax 进行指针初始化,就能够使得最后的结果可以完美输出
在这里我再一次感谢学习中帮助过我的人,好人一生平安!
语言表达能力有限,有不足之处,还望读者斧正。
本文完.