在 Assembly x86 中反转数组
Reverse an array in Assembly x86
我决定学习汇编(使用 emu8086),我想学习如何反转数组。
所以,我想将此代码从 C 转移到汇编:
void reverse(int len, char *str)
{
int i;
char temp;
for (i=len-1; i >= len/2; i--)
{
temp = str[i];
str[i] = str[len-1-i];
str[len-1-i] = temp;
}
}
这是数组
chrs db 'A','N','E','X','A','M','P','L','E','$'
这是主要的
mov ax, offset chrs
push ax
push 9
call reverse
到目前为止我可以自己处理它,直到我到达循环部分。
我学会了如何编写一个简单的循环,并且我还使用了这个 -
所以,我的主要问题是做反向功能。你能告诉我如何使用它吗?
谢谢
我将向您展示如何以不同的方式用 C 编写它。如果你能理解我所做的,一旦你更好地习惯了计算机内存设计以及 CPU 如何使用它,你应该能够稍后做你的 asm 循环。
void reverse(int len, char *str) {
char *bptr = str;
char *eptr = str+len-1;
char temp;
while (bptr < eptr) {
temp = *bptr;
*bptr = *eptr;
*eptr = temp;
++bptr;
--eptr;
}
}
这个C的循环体可以通过每行只使用一条x86指令转换成ASM,最初的while
可以通过在循环体之前使用两条指令和在循环体之后使用一条指令来完成.
你应该只用 mov
、inc
、dec
、cmp
、jae
、ret
就可以写出所有这些和 lea
或 add
.
顺便说一句,如果你想学习 ASM,请不要通过说明来记忆 "how to write loop",例如某种源代码列表,那是完全没有用的。您需要记住(1)每条指令的具体作用,并了解循环是如何通过它实现的。
CPU 是确定性状态机,每条指令确实以简单的确定性方式改变状态。所以一开始你有 CPU 处于某种状态,内存处于某种状态(可能包含一些输入数据,还有你的指令=代码),你知道你想在最后达到什么状态(两种状态CPU 和内存内容)。您只需使用指令将初始状态更改为结束状态。
例如,如果您的初始状态是 ax
包含值 5,并且您希望以包含值 6
的 ax
结束,您有多种方法可以实现,更短一个(每个只有一条指令)是:
mov ax,6
mov al,6
inc ax
inc al
浪费许多指令的荒谬方式可以是:
xor ax,ax
dec ah
shr ax,14
add ax,ax
所以死记硬背"listings"是没有用的,有很多方法可以达到你想要的状态。
(1) 不完全是,我几乎每次写一些 ASM 时都会检查 Intel 指令参考指南,即使在了解 x86 asm 20 多年之后也是如此。因为通常细节很重要,我必须确保指令完全符合我的预期。
我决定学习汇编(使用 emu8086),我想学习如何反转数组。 所以,我想将此代码从 C 转移到汇编:
void reverse(int len, char *str)
{
int i;
char temp;
for (i=len-1; i >= len/2; i--)
{
temp = str[i];
str[i] = str[len-1-i];
str[len-1-i] = temp;
}
}
这是数组
chrs db 'A','N','E','X','A','M','P','L','E','$'
这是主要的
mov ax, offset chrs
push ax
push 9
call reverse
到目前为止我可以自己处理它,直到我到达循环部分。
我学会了如何编写一个简单的循环,并且我还使用了这个 -
所以,我的主要问题是做反向功能。你能告诉我如何使用它吗? 谢谢
我将向您展示如何以不同的方式用 C 编写它。如果你能理解我所做的,一旦你更好地习惯了计算机内存设计以及 CPU 如何使用它,你应该能够稍后做你的 asm 循环。
void reverse(int len, char *str) {
char *bptr = str;
char *eptr = str+len-1;
char temp;
while (bptr < eptr) {
temp = *bptr;
*bptr = *eptr;
*eptr = temp;
++bptr;
--eptr;
}
}
这个C的循环体可以通过每行只使用一条x86指令转换成ASM,最初的while
可以通过在循环体之前使用两条指令和在循环体之后使用一条指令来完成.
你应该只用 mov
、inc
、dec
、cmp
、jae
、ret
就可以写出所有这些和 lea
或 add
.
顺便说一句,如果你想学习 ASM,请不要通过说明来记忆 "how to write loop",例如某种源代码列表,那是完全没有用的。您需要记住(1)每条指令的具体作用,并了解循环是如何通过它实现的。
CPU 是确定性状态机,每条指令确实以简单的确定性方式改变状态。所以一开始你有 CPU 处于某种状态,内存处于某种状态(可能包含一些输入数据,还有你的指令=代码),你知道你想在最后达到什么状态(两种状态CPU 和内存内容)。您只需使用指令将初始状态更改为结束状态。
例如,如果您的初始状态是 ax
包含值 5,并且您希望以包含值 6
的 ax
结束,您有多种方法可以实现,更短一个(每个只有一条指令)是:
mov ax,6
mov al,6
inc ax
inc al
浪费许多指令的荒谬方式可以是:
xor ax,ax
dec ah
shr ax,14
add ax,ax
所以死记硬背"listings"是没有用的,有很多方法可以达到你想要的状态。
(1) 不完全是,我几乎每次写一些 ASM 时都会检查 Intel 指令参考指南,即使在了解 x86 asm 20 多年之后也是如此。因为通常细节很重要,我必须确保指令完全符合我的预期。