Assembly 使用汇编语言程序交换两个字符串变量的内容
我是个新手。我试图交换两个字符串变量的内容。我有一个代码,用来交换两个内存变量。这是代码-Assembly 使用汇编语言程序交换两个字符串变量的内容,assembly,Assembly,我是个新手。我试图交换两个字符串变量的内容。我有一个代码,用来交换两个内存变量。这是代码- DATA SEGMENT NUM1 DB 9H NUM2 DB 7H ENDS CODE SEGMENT ASSUME DS:DATA CS:CODE START: MOV AX,DATA MOV DS,AX MOV AL,NUM1 MOV BL,NUM2 XCHG AL,NUM2 XCHG BL,NUM1 MOV AH,4CH INT 21H E
DATA SEGMENT
NUM1 DB 9H
NUM2 DB 7H
ENDS
CODE SEGMENT
ASSUME DS:DATA CS:CODE
START:
MOV AX,DATA
MOV DS,AX
MOV AL,NUM1
MOV BL,NUM2
XCHG AL,NUM2
XCHG BL,NUM1
MOV AH,4CH
INT 21H
ENDS
END START
请让我知道我是否可以在这里进行任何更改以获得准确的输出
MOV AL,NUM1
MOV BL,NUM2
XCHG AL,NUM2
XCHG BL,NUM1
可缩短为(完成时:相同内存、不同寄存器):
但实际上,这个较长的版本应该性能更好(XCHG
可能是非常昂贵的指令,因为它通常与LOCK
前缀一起用于多处理器PC中的同步,几十年来编译器都不使用它来“交换”值,因此在现代x86 CPU中它没有针对这一点进行优化):
现在您有两个标签NUM1
和NUM2
指向同一个字节,因此您有了单个“变量”的“别名”
最后是字符串
InputString DB "Hello$"
CPU中没有“字符串”这样的类型,因此InputString
不能是“字符串变量”。它只是下一个定义字节的标签,机器代码中下一个定义字节的值为'H'
,等于72
(检查ASCII表中特定ASCII字符的值)。该行将编译为6字节的机器代码,带有(十六进制)值:
所以要“交换两个字符串的内容”,您首先需要知道,两个目标内存位置都有足够的保留字节。例如:
String1 DB "a"
String2 DB "bc"
如果您尝试交换内容,则设置为灾难,因为只有1个字节为“String1”保留,因此当您将“bc”
写入其中时,'c'
将实际到达地址String2
当你知道你为两个“字符串”都保留了足够的内存时,你需要将字节内容从一个复制到另一个,反过来,你甚至可以忽略字符串的实际长度,只需逐个字节交换两个缓冲区的总内容(如buffer1 db 100 dup(?)
buffer2 db 100 dup(?)
然后在这两个字节之间交换100个字节,而不管里面是什么)。或者,当您在较长的一个标记中达到“字符串结束”标记时,您可以通过终止条件对其进行优化
还要注意的是,程序集中并没有字符串类型,所以如何标记字符串的结尾取决于代码。由int 21h,9
服务完成的DOS输出确实使用字符值'$'
,但您也可以使用以值0结尾的C类字符串,甚至可以使用旧的Pascal方式,将字符串的第一个字节保留为长度值,因此a=“Hello”以字节形式存储在内存中0548656C6F
。如果要使用int 21h,9
服务输出结果字符串,则必须覆盖'$'
终止符的末尾。(还要记住,字符串的终止符实际上是它的一部分,因此100字节的保留内存足以容纳长度为99个字符的零终止字符串)
继续使用调试器观察寄存器和内存中的值,以及它们随执行的每条指令的变化情况,这将极大地加快您的学习速度,因为它非常“直观”(与阅读《英特尔指令参考指南》相比,您仍应经常阅读该指南)
NUM1:
NUM2: DB 9
InputString DB "Hello$"
48 65 6C 6C 6F 24
String1 DB "a"
String2 DB "bc"