处理字符问题

字符在内存中的表现

在 汇编程序中,使用'...'单引号的方式来指明数据是以字符的形式给出的,编译器将把它们转化为相对应的ASCII码。

assume cs:code,ds:data
data segment
		db 'unIX'
		db 'foRX'
data ends

code segment
		start :
		mov al,'a'
		mov bl,'b'
		
		mov ax,4c00h
		int 21h
code ends
end start
assume cs:code,ds:data  ; 伪指令:关联段寄存器与段名(仅编译提示,无执行逻辑)
data segment            ; 数据段开始
    db 'unIX'           ; 定义4字节字符串:u(75H)、n(6EH)、I(49H)、X(58H)
    db 'foRX'           ; 定义4字节字符串:f(66H)、o(6FH)、R(52H)、X(58H)
data ends               ; 数据段结束

code segment            ; 代码段开始
start :                 ; 程序入口标签
    mov al,'a'          ; al = 61H(字符'a'的ASCII码)
    mov bl,'b'          ; bl = 62H(字符'b'的ASCII码)
    
    mov ax,4c00h        ; 设置中断功能号:4C(程序退出)
    int 21h             ; DOS中断:终止程序并返回DOS
code ends               ; 代码段结束
end start               ; 汇编结束,指定程序入口为start


DS=0E16 即DS:0 ,0E160H是程序开始的地址

程序开始的地址位置比数据段开始的地址位置(0E260H)小100H,这是因为:

在 DOS 系统中,当加载.COM.EXE程序时,系统会在程序实际代码前分配100H 字节(256 字节)程序段前缀(PSP),用于存储程序运行的环境信息(如命令行参数、DOS 中断向量、文件句柄等)。

‘unIX’‘foRX’这些字母都是对应的ASCII码存储在内存中的。

大小写字母ASCII表

大小写十六进制差值:对应大小写字母的十六进制差值为 0x20(十进制 32),例如:

  • 0x41 (A) + 0x20 = 0x61 (a)
  • 0x5A (Z) + 0x20 = 0x7A (z)
  • 本质是二进制第 5 位(0 开始计数)的差异(0x20 二进制为 00100000

大小写转换的问题

;大小写转换问题
assume cs:code,ds:data
data segment
		db 'BaSiC'
		db 'iNfOrMaTiOn'
data ends

code segment
		start :
		mov ax,data
		mov ds,ax
		
		;小写字母转换为大写字母
		mov bx,0
		mov cx,5
		s:mov al,[bx]
		and al,11011111B
		mov [bx],al
		inc bx
		loop s
		
		;大写字母转换为小写字母
		mov bx,5
		mov cx,11
		s0:mov al,[bx]
		or al,00100000B
		mov [bx],al
		inc bx
		loop s0
		
		mov ax,4c00h
		int 21h
code ends
end start

代码解读

assume cs:code,ds:data  ; 伪指令:关联段寄存器与段名
data segment            ; 数据段开始
    db 'BaSiC'          ; 定义第一个字符串(5字节:B(42H)、a(61H)、S(53H)、i(69H)、C(43H))
    db 'iNfOrMaTiOn'    ; 定义第二个字符串(11字节:i(69H)、N(4EH)、f(66H)...)
data ends               ; 数据段结束

code segment            ; 代码段开始
start :                 ; 程序入口标签
    mov ax,data         ; 数据段地址送入AX(直接给DS赋值非法,需通过AX中转)
    mov ds,ax           ; DS指向数据段,后续[bx]默认访问数据段

    ; ========== 第一段:小写转大写(处理前5个字符 'BaSiC')==========
    mov bx,0            ; 偏移地址初始化(从数据段0地址开始)
    mov cx,5            ; 循环次数=5(对应'BaSiC'的长度)
s:                      ; 循环标签
    mov al,[bx]         ; 取出当前偏移地址的字符(8位,ASCII码)
    and al,11011111B    ; 小写转大写:掩码第5位为0,其余位不变
    mov [bx],al         ; 转换后写回原地址
    inc bx              ; 偏移地址+1,指向下一个字符
    loop s              ; CX-1,若CX≠0则跳回s

    ; ========== 第二段:大写转小写(处理后续11个字符 'iNfOrMaTiOn')==========
    mov bx,5            ; 偏移地址=5(跳过前5个字符,指向第二个字符串起始)
    mov cx,11           ; 循环次数=11(对应'iNfOrMaTiOn'的长度)
s0:                     ; 循环标签
    mov al,[bx]         ; 取出当前字符
    or al,00100000B     ; 大写转小写:掩码第5位为1,其余位不变
    mov [bx],al         ; 转换后写回
    inc bx              ; 偏移地址+1
    loop s0             ; CX-1,若CX≠0则跳回s0

    mov ax,4c00h        ; DOS中断功能号:程序正常退出
    int 21h             ; 触发中断,退出程序
code ends               ; 代码段结束
end start               ; 汇编结束,指定程序入口为start

posted @ 2025-12-05 09:28  chenlight  阅读(3)  评论(0)    收藏  举报  来源