Assembly 程序集x64 linux TictaToe上的分段故障

Assembly 程序集x64 linux TictaToe上的分段故障,assembly,segmentation-fault,x86-64,tic-tac-toe,Assembly,Segmentation Fault,X86 64,Tic Tac Toe,我对16位MSDO的TictaToe进行了改编,以在64位linux上工作 section .bss game_position_pointer resb 9 key resb 1 section .data new_line db 10 nl_size equ $-new_line game_draw db "_|_|_", 10 db "_|_|_", 10 db "_|_|_", 10, 0 gd_size equ $-game_draw w

我对16位MSDO的TictaToe进行了改编,以在64位linux上工作

section .bss
game_position_pointer resb 9
key resb 1

section .data
new_line db 10
nl_size equ $-new_line

game_draw db "_|_|_", 10 
          db "_|_|_", 10
          db "_|_|_", 10, 0
gd_size equ $-game_draw

win_flag db 0

player db "0", 0
p_size equ $-player

game_over_message db "FIM DE JOGO AMIGOS", 10, 0
gom_size equ $-game_over_message

game_start_message db "JOGO DA VELHA"
gsm_size equ $-game_start_message

player_message db "JOGADOR ", 0
pm_size equ $-player_message

win_message db " GANHOU!", 0
wm_size equ $-win_message

type_message db "ENTRE COM UMA POSICAO NO TABULEIRO: ", 0
tm_size equ $-type_message

clear_screen_ASCII_escape db 27,"[H",27,"[2J"      ; <ESC> [H  <ESC>  [2J
cs_size equ $-clear_screen_ASCII_escape

section .text 
global _start 

_start:
call set_game_pos_pointer

main_loop:
call clear_screen

mov rsi, game_start_message
mov rdx, gsm_size
call print

mov rsi, new_line
mov rdx, nl_size
call print

mov rsi, player_message
mov rdx, pm_size
call print

mov rsi, player
mov rdx, p_size
call print

mov rsi, new_line
mov rdx, nl_size
call print

mov rsi, game_draw
mov rdx, gd_size
call print

mov rsi, new_line
mov rdx, nl_size
call print

mov rsi, type_message
mov rdx, tm_size
call print

call read_keyboard               ; Vamos ler a posição que o usuário vai passar

mov al, [key]
sub al, 49                       ; 49 equivale a "1" em ASCII, eu faço essa subtração porque eu quero converter ASCII para inteiro, ao mesmo tempo que faço subtraio de 1 o valor inteiro


call update_draw

call check

cmp byte[win_flag], 1
je game_over

call change_player

jmp main_loop

change_player:

mov rsi, player
xor byte[rsi], 1  ; Tipo um xor swap :)

ret

print:
mov rax, 1
mov rdi, 1
syscall
ret

read_keyboard:
mov rax, 0
mov rdi, 0
mov rsi, key 
mov rdx, 1
syscall

ret

clear_screen:
mov rsi, clear_screen_ASCII_escape
mov rdx, cs_size
call print
ret

set_game_pos_pointer:
mov rsi, game_draw
mov rbx, game_position_pointer

mov rcx, 9

loop_1:
    mov [rbx], rsi
    add rsi, 2

    inc rbx
    loop loop_1

ret

update_draw:
lea rbx, [game_position_pointer + rax]

mov rsi, player

cmp byte[rsi], "0"
je draw_x

cmp byte[rsi], "1"
je draw_o

draw_x:
    mov cl, "x"
    jmp update

draw_o:
    mov cl, "o"
    jmp update

update:

    mov [rbx], cl


ret

check:
call check_line
ret

check_line:

mov rcx, 0

check_line_loop:
    cmp rcx, 0
    je first_line

    cmp rcx, 1
    je second_line

    cmp rcx, 2
    je third_line

    call check_column
    ret

    first_line:
        mov rsi, 0
        jmp do_check_line

    second_line:
        mov rsi, 3
        jmp do_check_line

    third_line:
        mov rsi, 6
        jmp do_check_line

    do_check_line:
        inc rcx

        lea rbx, [game_position_pointer + rsi]
        mov al, [rbx]
        cmp al, "_"
        je check_line_loop

        inc rsi
        lea rbx, [game_position_pointer + rsi]
        cmp al, [rbx]
        jne check_line_loop

        inc rsi
        lea rbx, [game_position_pointer + rsi]
        cmp al, [rbx]
        jne check_line_loop

    mov byte[win_flag], 1
    ret

check_column:
mov rcx, 0

check_colum_loop:
    cmp rcx, 0
    je first_column

    cmp rcx, 1
    je second_column

    cmp rcx, 2
    je third_column

    call check_diagonal
    ret

    first_column:
        mov rsi, 0
        jmp do_check_column

    second_column:
        mov rsi, 1
        jmp do_check_column

    third_column:
        mov rsi, 2
        jmp do_check_column

    do_check_column:
        inc rcx

        lea rbx, [game_position_pointer + rsi]
        mov al, [rbx]
        cmp al, "_"
        je check_colum_loop

        add rsi, 3
        lea rbx, [game_position_pointer + rsi]
        cmp al, [rbx]
        jne check_colum_loop

        add rsi, 3
        lea rbx, [game_position_pointer + rsi]
        cmp al, [rbx]
        jne check_colum_loop

        mov byte[win_flag], 1
        ret

check_diagonal:
mov rcx, 0

check_diagonal_loop:
    cmp rcx, 0
    je first_diagonal

    cmp rcx, 1
    je second_diagonal

    ret

first_diagonal:
    mov rsi, 0
    mov rdx, 4          ; tamanho do pulo que vamos dar para o meio da diagonal 
    jmp do_check_diagonal

second_diagonal:
    mov rsi, 2
    mov rdx, 2
    jmp do_check_diagonal

do_check_diagonal:
    inc rcx

    lea rbx, [game_position_pointer + rsi]
    mov al, [rbx]
    cmp al, "_"
    je check_diagonal_loop

    add rsi, rdx
    lea rbx, [game_position_pointer + rsi]
    cmp al, [rbx]
    jne check_diagonal_loop

    add rsi, rdx
    lea rbx, [game_position_pointer + rsi]
    cmp al, [rbx]
    jne check_diagonal_loop

mov byte[win_flag], 1
ret

game_over:
call clear_screen

mov rsi, game_start_message
mov rdx, gsm_size
call print

mov rsi, new_line
mov rdx, nl_size
call print

mov rsi, game_draw
mov rdx, gd_size
call print

mov rsi, new_line
mov rdx, nl_size
call print

mov rsi, game_over_message
mov rdx, gom_size
call print

mov rsi, player_message
mov rdx, pm_size
call print

mov rsi, player
mov rdx, p_size
call print

mov rsi, win_message
mov rdx, wm_size
call print

jmp fim

fim:
mov rax, 60
mov rdi, 0
syscall
我只是不明白我做错了什么。如有任何建议或帮助,将不胜感激

编辑: 我编辑了添加建议的代码,奇怪的是,我发现change\u player标签没有改变任何东西,事实上,我的整个代码似乎没有修改节数据的变量。比如说,

change_player:
    mov si, player
    xor byte[si], 1  ; Tipo um xor swap :)
    ret

如果不更改变量player,则值始终为“0”

一些位看起来可疑,尤其是

mov bl, byte[game_position_pointer + rax]

bl覆盖rbx的最低8位,因此操作看起来像是将字节从“rax”中的板位置移动到bl中。rbx随后用作指针(即,您的故障指令)

在第二个示例中,其目的似乎是将线路板位置的地址加载到rbx中,然后获取该位置的值。那看起来像

lea rbx, [game_position_pointer + rsi]
mov al, [rbx]
还是更简洁

mov al, game_position_pointer[rsi]
抱歉,如果我把语法弄错了,我不熟悉你的汇编语言风格。GNU提供了更精确的语法。

在:

mov rbx, [game_position_pointer + rsi]

mov al,[rbx]
您使用位置
[game\u position\u pointer+rsi]
中的值作为导致分段错误的指针,您需要使用
game\u position\u pointer+rsi
位置本身

**我不知道它是否适用于你的游戏,或者你可以直接使用它

mov al ,byte[game_position_pointer + rsi]

segfault在哪个指令上?使用
gdb
查找。这是一个几乎没有任何注释的大规模代码转储,与。哦,代码后面有文本,我只是在修改了你的格式后才看到的。此时,
rbx
中的值是多少(使用调试器检查。
mov bl,byte[game\u position\u pointer+rax]
写入RBX的低位字节,因此看起来很可疑,除非在到达使用RBX作为指针的指令之前,有其他东西将其设置为有效指针,或者如果您正在索引到256字节对齐的内容,并且部分寄存器写入是一种进行数组索引的黑客方法。
mov si,[player]
是一个加载,它替换了
si
中以前的值。您是想用
mov[player]存储吗,si
?x86-64有很多寄存器;您可能根本不需要内存,例如,
xor r15d,1
。使用调试器单步执行,下次遇到问题时检查寄存器。实际上我忘了编辑最后一部分,现在看看它。xor正在按它应该的方式工作,我在这些变量中编写的任何内容实际上都没有被修改另一个例子是更新画图标签,线条mov[rbx],cl似乎没有任何效果。我编辑了代码并做了一些修改,比如lea rbx[game_position_pointer+rsi]Thx作为回复!数组game_position_pointer的内容是9个地址,这就是为什么我使用位置[game_position_pointer+rsi]中的值作为指针。但导致seg f。我不知道如何取消对地址的引用。再说一次,masm语法很混乱,但您似乎将player用作指针而不是标签。我很惊讶您没有得到太多SEGV。当我说“混乱”时,gas的“粗糙”语法的好处是,您明确区分了加载地址和值;而DOS asm掩盖了这一点。我在这里测试,发现sys\u read在我键入位置后读取“\n”,因此它跳过下一个循环并返回“0”,使得impression player变量从未改变。哈哈。尽管如此,问题仍然存在,在game_position_指针中,函数集_game_position_指针应该将棋盘的每个正方形与位置关联,当调用update_draw时,指针工作正常,但字符串game_draw不受影响。
mov rbx, [game_position_pointer + rsi]

mov al,[rbx]
mov al ,byte[game_position_pointer + rsi]