使用交换方法x86 MASM反转程序集中的外部阵列
Reverse external array in assembly using swapping method - x86 MASM
我正在处理一个项目,我们需要传递一个char类型的数组作为参数,并反转该数组。我觉得我很快就要完成了,但我被困在了实际的交换过程中。
对于.asm中的交换函数,我使用了与c++中相同的方法(使用一个未使用的寄存器作为临时寄存器,然后交换前面和后面。)我不明白的是,我该如何更改该地址的实际内容。我认为执行以下操作会"更改"目的地地址的内容:
mov eax,[edx]
然而,这并没有按计划进行。在我运行for循环以再次遍历数组之后,一切都保持不变。
如果有人能给我指明正确的方向,那就太好了。我已经在下面的代码中提供了尽可能多的评论。
此外,我在一个.asm文件中完成所有这些操作;然而,我的教授希望我为以下每个函数都有3个单独的.asm文档:swap、reverse和getLength。我试图将另一个2.asm文档包含在reverse.asm中,但它一直给我一个错误。
程序集代码启动:
.686
.model flat
.code
_reverse PROC
push ebp
mov ebp,esp ;Have ebp point to esp
mov ebx,[ebp+8] ;Point to beginning of array
mov eax,ebx
mov edx,1
mov ecx,0
mov edi,0
jmp getLength
getLength:
cmp ebp, 0 ;Counter to iterate until needed to stop
je setup
add ecx,1
mov ebp,[ebx+edx]
add edx,1
jmp getLength
setup: ;This is to set up the numbers correctly and get array length divided by 2
mov esi,ecx
mov edx,0
mov eax,ecx
mov ecx,2
div ecx
mov ecx,eax
add ecx,edx ;Set up ecx(Length of string) correctly by adding modulo if odd length string
mov eax,ebx
dec esi
jmp reverse
reverse: ;I started the reverse function by using a counter to iterate through length / 2
cmp edi, ecx
je allDone
mov ebx,eax ;Set ebx to the beginning of array
mov edx,eax ;Set edx to the beginning of array
add ebx,edi ;Move ebx to correct index to perform swap
add edx,esi ;Move edx to the back at the correct index
jmp swap ;Invoke swap function
swap:
mov ebp,ebx ;Move value to temp
mov ebx,[edx] ;Swap the back end value to the front
mov edx,[edx] ;Move temp to back
inc edi ;Increment to move up one index to set up next swap
dec esi ;Decrement to move back one index to set up for next swap
jmp reverse ;Jump back to reverse to setup next index swapping
allDone:
pop ebp
ret
_reverse ENDP
END
C++代码启动:
#include <iostream>
#include <string>
using namespace std;
extern "C" char reverse(char*);
int main()
{
const int SIZE = 20;
char str1[SIZE] = { NULL };
cout << "Please enter a string: ";
cin >> str1;
cout << "Your string is: ";
for (int i = 0; str1[i] != NULL; i++)
{
cout << str1[i];
}
cout << "." << endl;
reverse(str1);
cout << "Your string in reverse is: ";
for (int i = 0; str1[i] != NULL; i++)
{
cout << str1[i];
}
cout << "." << endl;
system("PAUSE");
return 0;
}
因此,经过数小时的修补和环顾四周,我终于能够找到如何正确地复制一个字节。如果有人需要的话,我会在下面发布我的.asm代码并附上评论,以备将来参考。
实际上,我正在将当前地址的内容移动到32位寄存器中。在我将其从mov ebx,[eax]更改为mov bl,[eax] 我只会发布我遇到困难的代码,所以我不会把整个项目泄露给其他学生。 下面的ASM代码: 感谢所有提供帮助的人。swap:
mov bl,[edx] ;Uses bl since we are trying to copy a 1 byte char value
mov bh,[eax] ;Uses bh since we are trying to copy a 1 byte char value
mov [edx],bh ;Passing the value to the end of the array
mov [eax],bl ;Passing the value to the beginning of the array
inc eax ;Moving the array one index forward
dec edx ;Moving the array one index backwards
dec ecx ;Decreasing the counter by one to continue loop as needed
jmp reverse ;Jump back to reverse to check if additional swap is needed
mov eax,[edx]
(假设intel语法)将在地址edx的内存中找到的32位放入eax。即,此代码从内存位置检索数据。如果你想写入内存位置,你需要反向,即mov [edx], eax
在一夜之间玩了一些16位代码进行排序之后,我有了以下两个可能有用的函数。显然,你不能复制/粘贴它们,你必须研究一下。然而,你会注意到它可以交换任意大小的物品。非常适合交换某种类型的结构元素。
; copies cx bytes from ds:si to es:di
copyBytes:
shr cx, 1
jnc .swapCopy1Loop
movsb
.swapCopy1Loop:
shr cx, 1
jnc .swapCopy2Loop
movsw
.swapCopy2Loop:
rep movsd
ret
; bp+0 bp+2 bp+4
;void swap(void *ptr1, void *ptr2, int dataSizeBytes)
swapElems:
push bp
mov bp, sp
add bp, 4
push di
push si
push es
mov ax, ds
mov es, ax
sub sp, [bp+4] ; allocate dataSizeBytes on the stack, starting at bp-6 - dataSizeBytes
mov di, sp
mov si, [bp+0]
mov cx, [bp+4]
call copyBytes
mov si, [bp+2]
mov di, [bp+0]
mov cx, [bp+4]
call copyBytes
mov si, sp
mov di, [bp+2]
mov cx, [bp+4]
call copyBytes
add sp, [bp+4]
pop es
pop si
pop di
pop bp
ret 2 * 3
- 内联程序集printf将整数解释为地址
- 正在解码MSVC 32位版本的程序集(作业).没有手术做什么
- 具有外部"c"和程序集的未定义函数
- 用于将C++代码转换为 Web 程序集的脚本未终止
- 为什么我的C++程序的程序集输出充满了 .ascii,没有汇编代码?
- CoreCLR 中的检测探查器 - 将帮助程序程序集加载到 dotnet 进程的方法
- 不同于按值传递和常量引用传递的程序集
- 为什么在堆栈和堆上创建变量会产生相同的程序集代码?
- C++变量在调用 x64 程序集函数后重置为 0
- 如何将C++子例程链接到 x86 程序集程序?
- Qt 网页程序集缓存
- 测试操作系统时执行程序集"sti"时虚拟框崩溃
- 为什么从 constexpr 引用生成的程序集代码与从 constexpr 指针生成的程序集代码不同?
- 将内联程序集尾调用函数尾声替换为用于x86/x64 msvc的Intrinsics
- 解析 C# 中的C++程序集
- 64 位进程中的 AnyCPU C# DLL 无法引用 64 位C++ DLL(给出错误:无法加载文件或程序集)
- 使用CLANG内联程序集创建C++预增量操作
- 是否可以在C++中基于程序集输出(.dll或.exe)定义变量
- 用于比较基元类型的std::可选的有趣程序集
- 简单加密程序集程序-写入内存位置时发生访问冲突