[toc]
ASCII(发音: /ˈæski/ ASS-kee[1],American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语,而其扩展版本延伸美国标准信息交换码则可⒗以部分支持其他西欧语言,并等同于国际标准**ISO/IEC 646**。
ASCII 由电报码发展而来。第一版标准发布于1963年[3][4],1967年经历了一次主要修订[5][6],最后一次更新则是在1986年,至今为止共定义了128个字符;其中33个字符无法显示(一些终端提供了扩展,使得这些字符可显示为诸如笑脸、扑克牌花式等8-bit符号),且这33个字符多数都已是陈废的控制字符。控制字符的用途主要是用来操控已经处理过的文字。在33个字符之外的是95个可显示的字符。用键盘敲下空白键所产生的空白字符也算1个可显示字符(显示为空白)。
注意这里我调用了int 21h
,这是一个DOS的中断,其中ah=09是他的功能号用来打印字符串。
关于DOS中断的内容会在后续章节详细介绍。
assume cs:code,ds:data
;>>>>>>>>>>>>>>>>
;数据段
;>>>>>>>>>>>>>>>>
data segment
db 'hello,world!','$'
data ends
;>>>>>>>>>>>>>>>>
;代码段
;>>>>>>>>>>>>>>>>
code segment
start:
mov ax,data
mov ds,ax
;调用DOS中断显示字符串
mov dx,0 ;ds:[dx]
mov ah,09h
int 21h
;return dos
mov ax,4c00h
int 21h
code ends
end start
小写字母的ASCII码值比大写字母的ASCII码值大20H(32)
大写字母ASCII码的第5位为0,小写字母的第5位为1(其他一致)
;**********************************
;* *
;* 要求:将所有字符串转换成小写字符串 *
;**********************************
assume cs:code,ds:data
;>>>>>>>>>>>>>>>>>
;数据段
;>>>>>>>>>>>>>>>>>
data segment
db 'Hello,World!','$'
data ends
;>>>>>>>>>>>>>>>>>
;代码段
;>>>>>>>>>>>>>>>>>
code segment
main:
mov ax,data ;ds段
mov ds,ax
;大小写转换
mov bx,0
mov cx,11
s: mov al,ds:[bx] ;将ASCII码从 ds:bx单元中取出
or al,00100000b;让第5位无论如何都变1
mov ds:[bx],al
inc bx
loop s
;输出字符串
mov dx,0; ds:[0]
mov ah,09h
int 21h
;retun 2 dos
mov ax,4c00h
int 21h
code ends
end main
在前面,我们用[bx]的方式来指明一个内存单元,还可以用一种更为灵活的方式来指明内存单元:[bx+idata]表示一个内存单元,他的偏移地址为(bx)+idata [bx中的数值加上数字]
例如: mov ax,[bx+200]
也可以写成如下的格式:(注意这里指的是masm所支持的伪指令,具体其他编译器看情况而定.)
mov ax,[bx+200]
mov ax,[200+bx]
mov ax,[bx].200
mov ax,200[bx]
[bx+idata]处理数组例子:
;*************************************
;* *
;* 将如下的doSASM转换成DOSasm *
;*************************************
assume cs:code,ds:data
;>>>>>>>>>>>>>>>>>>>>>
;数据段
;>>>>>>>>>>>>>>>>>>>>>
data segment
db 'doS'
db 'asm','$'
data ends
;>>>>>>>>>>>>>>>>>>>>>
;代码段
;>>>>>>>>>>>>>>>>>>>>>
code segment
main:
;
mov ax,data
mov ds,ax
;大小写转换
mov bx,0
mov cx,3
s:mov al,0[bx]
and al,11011111b;转大写
mov 0[bx],al
mov al,3[bx];
or al,00100000b;转小写
mov 3[bx],al
inc bx
loop s
;输出字符串
mov dx,0
mov ah,09h
int 21h
;return 2 DOS
mov ax,4c00h
int 21h
code ends
end main
翻译成C语言
#include <stdio.h>
int main()
{
char a[]="doS";
char b[]="ASM";
int i=0;
do
{
a[i] = a[i] & 0xDF;
b[i] = b[i] | 0x20;
i++;
}while(i<3);
printf("%s%s\n",a,b);
return 0;
}
这两个寄存器其实之前介绍寄存器篇章的时候,已经介绍过了,si和di都是偏移寄存器并且注意在x86架构下,他们是字符串相关的寄存器。
如果我们比较一下前面用到的集中定位内存地址的方法(可以称为寻址方式),就可以发现:
- [idata]用一个常量来表示地址,可用于直接定位一个内存单元;
- [bx]用一个变量来表示内地地址,可用于间接定位一个内存单元(比如循环);
- [bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元(比如多个数组);
- [bx+si]用两个变量表示地址;
- [bx+si+idata]用连个变量和一个常量表示地址。
可以看到,从[idata]一直到[bx+si+idata],我们可以用更加灵活的方式来定位一个内存单元的地址。这使得我们可以从更结构化的角度
来看待所要处理的数据。
参考文献: https://blog.csdn.net/trochiluses/article/details/20008631 int 21——dos系统调用 表 https://blog.csdn.net/qq_39654127/article/details/88698911 王爽汇编笔记 《王爽汇编第4版》 第7章