3

おそらく明らかに間違ったことをしているのですが、興味深い問題があるようです。

私の問題は、AAAABBBBCCCC をスタックにプッシュし、標準出力で出力しようとしていることです。ただし、私の x86_64 環境では、 がpush 0x41414141プッシュされているようです4141414100000000

したがって、次のコード ブロック:

    global _start
    section .text
    _start:
    push 0x43434343  ; CCCC
    push 0x42424242  ; BBBB
    push 0x41414141  ; AAAA
    xor rax,rax      ; Zero RAX
    mov byte al,0x1  ; 1 for sys_write
    mov rdi,rax      ; 1 for stdout
    mov rsi,rsp      ; RSP for source
    mov byte dl,0xC  ; 12
    syscall          

    xor rax,rax      ; Zero RAX
    mov al, 0x3C     ; 60 for sys_edxit
    cdq              ; 0 for clean exit.
    syscall

OutputsAAAABBBBは、たった 8 バイトだと思っていたのですが、実際には私が要求した 12 バイトでした。出力ファイルにパイプしてhexeditで見ると、表示されていることに気付きました414141410000000042424242.

push命令が値をプッシュすると思いdwordます。サイズqwordのスタックに?私はこれを考えるのが正しいですか?

これは、余分なバイトを考慮に入れ、長さを 20 に変更することで簡単に回避できますsys_open

だから私の質問は、私は何が間違っているのですか?

4

1 に答える 1

11

64ビットコードの場合、スタック(RSP)は常に8バイト境界に配置されます。「pushqwordimm64」命令もありません(注を参照)。

私のアドバイスは、文字列 "AAAABBBBCCCC"を、スタックをいじるのではなく、それが属するデータセクション(または ".rodata")に格納することです。またはシェルコードで、

push   'CCCC'                  ; push qword, including 4 bytes of zeros
mov    rax, 'AAAABBBB'         ; mov reg, imm64; pick any register
push   rax                     ; push qword

あなたの倒錯を維持する代替案は次のようになります:

sub rsp,16
mov dword [rsp],'AAAA'
mov dword [rsp+4],'BBBB'
mov dword [rsp+8],'CCCC'
....
add rsp,16

注:AMDのマニュアルには、「pushimm64」の説明があると記載されています。AMDのマニュアルは間違っています-この命令は実際には32ビットのイミディエートをプッシュします(64ビットへの符号拡張付き)。

Intelのマニュアルにはその問題はありません:https
://www.felixcloutier.com/x86/push 関連項目:オペランドサイズを指定しない場合、プッシュ命令はスタックに何バイトプッシュしますか?--64ビットモードでは絶対にdwordプッシュを実行できません。

于 2012-09-22T15:20:52.797 に答える