90277


x86 の intel syntax にて、グローバル変数の値には `[rip+a]` でアクセスできるのですが、`mov [rip+a], 4`
のように、グローバル変数のアドレスへ新しい値を代入しようとすると、Segmentation Fault
が発生します。他のレジスタの操作と同様にできると思い上記のように書こうとしていたのですが、それではダメなようで。

Segmentation Fault となるコードは下記です。

[code]

    .intel_syntax noprefix
    .globl main
    
    a:
      .int 8
    main:
      push rbp
      mov rbp, rsp
      sub rsp, 0
      push [rip+a]
      pop rax
      mov dword ptr [rip+a], 4  // この行を追加すると Segmentation Fault が発生
      mov rsp, rbp
      pop rbp
      ret
    
[/code]

<https://godbolt.org/> では intel syntax
でアセンブリを出力する方法が見つからず、検索しても上記に関する情報が見つからず、質問させていただきました。


CC BY-SA 4.0
2022-07-29T22:11:22.370
90276
2022-07-29T23:06:17.810
25693
question
assembly x86
x86 intel syntax のアセンブリにおけるグローバル変数への代入方法がわかりません。


> グローバル変数の値には `[rip+a]` でアクセスできるのですが
[code]

>       push [rip+a]
>       pop rax
>       mov dword ptr [rip+a], 4  // この行を追加すると Segmentation Fault が発生
>  
[/code]

いいえ、全く違います。 `RIP`
は現在実行している命令のアドレスが格納されています。つまり`[rip+a]`は現在実行している命令からの相対値となります。`push
[rip+a]`で参照されるアドレスと`mov dword ptr [rip+a], 4`で書き込もうとするアドレスは別となります。  
正しくは

[code]

      movzx rax, dword ptr [a]
      mov dword ptr [a], 4
    
[/code]

で可能です。

* * *

ただし、セキュリティ上、コード領域は書き換えられるべきではなく読み取り専用に設定されていることが一般的です。

>
[code]

>     a:
>       .int 8
>     main:
>       push rbp
>  
[/code]

ということは `a` は `main` の４バイト手前であり、コードと同様に読み取り専用とされている可能性が高いです。 `a`
は書き換え可能に設定されているセグメントに配置されるべきです。


CC BY-SA 4.0
2022-07-29T23:06:17.810
90277
2022-07-29T23:06:17.810
4236
90276
answer