MacOS汇编寻址问题:字符移位程序触发段错误求助
解决MacOS下汇编段错误的问题
核心问题分析
你的代码在Windows正常但MacOS报错,主要是三个原因:
- MacOS默认是64位编译环境,原代码用32位寄存器(
eax/ecx等)存储64位地址会被截断,导致非法内存访问。 - Windows的
__asm是MASM语法,MacOS下clang的__asm(通过-fasm-blocks启用)对栈变量的寻址逻辑有差异,32位指令集的寻址方式不兼容。 loop指令在64位模式下的行为与32位不同,容易引发逻辑错误。
修改后的可运行代码
#include <string> #include <iostream> using namespace std; int main() { string str1 = "Hello world!"; char* str = &str1[0]; int str_len = str1.length(); __asm { // 将字符串地址加载到64位寄存器rax mov rax, str // 将字符串长度加载到rcx,循环次数减1 mov rcx, str_len dec rcx // 定位到字符串最后一个字符 mov rsi, rax add rsi, rcx mov dl, [rsi] shift: // 从后往前逐个移动字符 mov rbx, rsi dec rbx mov al, [rbx] mov [rsi], al dec rsi // 手动控制循环(替代loop指令,避免64位模式兼容问题) dec rcx jnz shift // 将最后一个字符放到第一个位置 mov [rsi], dl } cout << str; }
关键修改点
- 切换到64位寄存器:用
rax/rcx/rsi/rbx等64位寄存器替代32位寄存器,确保能完整存储MacOS的64位内存地址,避免地址截断导致的段错误。 - 替换
loop指令:用dec rcx + jnz shift手动实现循环逻辑,规避loop指令在64位模式下的行为差异,同时提升执行效率。 - 匹配寻址宽度:所有地址操作都使用64位寄存器,确保内存访问的地址长度正确,不会出现越界或非法访问。
针对你给出的段错误示例的修复
原示例中用32位寄存器存储64位地址导致截断,修改为64位寄存器即可解决:
char* str = &str1[0]; __asm { mov rax, str mov rdx, [rax] }
编译验证
继续使用你原来的编译命令即可:
g++ -o asm asm.cpp -fasm-blocks -std=c++17
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

