我是asm的新手,并尝试使用一些操作码来获取它。 我正在研究linux,64位,并且在使用movsb时总是出现分段错误。我用nasm编译:
nasm -f elf64 test.asm
这是代码
DEFAULT ABS
segment data
data:
texte: db 'Hello, World !!', 10, 13
len: equ $-texte
texteBis: db 'Hello, World !.', 10, 13
segment code
global main
main:
;The problem is here
mov rsi, texteBis
mov rdi, texte
mov cx, len
rep movsb
mov dx, len
mov rcx, texte
mov bx, 1
mov ax, 4
int 0x80
mov bx,0 ; exit code, 0=normal
mov ax,1 ; exit command to kernel
int 0x80 ; interrupt 80 hex, call kernel
其他问题,使用字符串(或其他大型数据库实例),我应该使用
mov rsi, texte
或
mov rsi, [texte]
我不明白哪一个给出了价值,哪一个给了地址。
答案 0 :(得分:1)
你还链接吗?
ld -e main test.o -o test
无论如何,texteBis
似乎是数据段中的静态数据。该页面是只读的并受保护以便写入/执行。
如果允许使用运行时库,则应分配缓冲区(在堆栈上或堆上)。
答案 1 :(得分:1)
您的问题是您正在写入写保护内存,即DATA
部分。程序加载到内存后,DATA
部分实际上是在只读页面上。您必须使用堆栈内存(或动态分配的内存)并将其用作字符串副本的目标。
示例:
sub rsp, len ; move stack pointer down 'len' bytes
mov rsi, texteBis
mov rdi, rsp ; use address of stack pointer as dest.
xor rcx,rcx ; cx = 0
mov cx, len
rep movsb
那应该可以解决你的问题。与在C中一样,分配足够的空间很重要,否则您将覆盖堆栈上的数据。
我注意到的另一件事是你经常写寄存器的子部分,例如
mov dx, len
这很危险,因为其他部分不会被此覆盖。仅写入寄存器的最低16位。说rdx
,64位值设置为0xffffffffffffffff
。移动后rdx
看起来像这样:0xffffffffffff0011
。调用代码可能完全读取rdx
,因此解释0xffffffffffff0011
字节的长度。不是你想要的。解决方案:
xor rdx,rdx
mov dx, len
或
mov rdx, len
注意,gdb
将帮助您找到错误发生的位置,并且还会为您提供其他信息(例如寄存器值和堆栈值)。摘录:
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005bb in main ()
(gdb) disassemble
Dump of assembler code for function main:
0x00000000004005a6: sub $0x13,%rsp
0x00000000004005aa: mov -0x1c(%rip),%rsi # 0x400595
0x00000000004005b1: mov %rsp,%rdi
0x00000000004005b4: xor %cx,%cx
0x00000000004005b7: mov $0x11,%cx
=> 0x00000000004005bb: rep movsb %ds:(%rsi),%es:(%rdi)
0x00000000004005bd: mov $0x11,%dx
0x00000000004005c1: movabs $0x400584,%rcx
0x00000000004005cb: mov $0x1,%bx
0x00000000004005cf: mov $0x4,%ax
0x00000000004005d3: int $0x80
0x00000000004005d5: mov $0x0,%bx
0x00000000004005d9: mov $0x1,%ax
0x00000000004005dd: int $0x80
End of assembler dump.
(gdb) info registers rsi
rsi 0x57202c6f6c6c6548 6278066737626506568
由于nasm
不支持有用的调试格式,但通常情况下您希望在某些情况下中断,您可以使用int3
指令在SIGTRAP
处引发 mov eax, 10
int3 ; debugger will catch signal here
代码中的某一点:
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return nil
}
希望这有助于您开始组装。
答案 2 :(得分:1)
您不需要使用动态内存。您的数据段或部分是只读的,因为它不是标准部分,您没有定义它的属性,默认情况下,nasm将它们指定为只读数据部分。
在代码中使用objdump -h
输出以下内容:
0 data 00000022 0000000000000000 0000000000000000 00000200 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 code 0000003c 0000000000000000 0000000000000000 00000230 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
如果您将分段的名称更改为.data
和.text
,该程序将完美运行并objdump
输出:
0 .data 00000022 0000000000000000 0000000000000000 00000200 2**2
CONTENTS, ALLOC, LOAD, DATA
1 .text 0000003c 0000000000000000 0000000000000000 00000230 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
您打算使用哪些部分的正确属性。
要了解有关属性的更多信息,请参阅此页面: https://www.tortall.net/projects/yasm/manual/html/objfmt-elf-section.html