0

配列内の最大要素を見つけることができるプログラムに取り組んでいます。何らかの理由で、マトリックスの最初の要素を出力用の ecx レジスタに移動しようとすると (テストするだけです)、セグメンテーション違反が発生します。

確実にするために、さまざまな種類のアドレス指定モードをすべて試しましたが、なぜこのエラーが発生し、何も機能しないのかわかりません。

これが私のコードです:

segment .data

    NUM_ROWS: equ 5
    NUM_COLUMNS: equ 5
    NUM_ROW_BYTES: equ 10

    ;Default matrix
    matrix: dd  5, 4, 9, 7, 2, 1, 4, 6, 8, 7
            ;9, 9, 2, 3, 7
            ;6, 5, 8, 3, 4
            ;1, 2, 8, 2, 6  
    matrixLen: equ $-matrix

    sum:    db "The sum of the last column is: ", 10

    ;FOR TESTING
    works: db 'Works!', 10
    worksLen: equ $-works

segment .bss
    counter resb 1

segment .text
    global main

main:
    mov eax, 4      ; system call 4
    mov ebx, 1      ; standard output 
    mov ecx, [matrix + 4]   
    mov edx, 4
    int 0x80
4

1 に答える 1

0

私が見つけたLinuxシステムコールのリストを調べていますが、1文字だけを出力する呼び出しはないようです。sys_write()を使用してスタックしていますが、EDXを1に設定して有効なポインターを渡すと、1文字を出力できます。

mov ecx, [matrix + 4]sys_writeがそれをアドレスとして使用するように、(matrix + 4)が指すの値のみをECXに移動することを認識してください。そのアドレスには4が含まれているため、sys_writeはアドレス0x00000004から始まる文字列データを出力しようとしました。それがセグフォールトした理由です(そこから読み取ることは許可されていません)。

値4を印刷に適したASCII値に変換するには、値に0x30を追加します。ASCII 0x30 = '0'、0x31 = '1' ... 0x34 = '4' ... 0x39='9'。

したがって、1桁を印刷するための戦略は、その桁をECXにロードし、0x30を追加し、.bssセグメントで予約したバイトに押し込み(多分)、 sys_writeを呼び出す前にdigit_to_ascii resb 1のアドレスをECXに移動することです(EDXのみを設定します)。 digit_to_ascii1バイトだけを印刷したいので1に)。

これは1桁の印刷でのみ機能することを理解してください。10以上の数値を印刷する場合は、各桁を除算して個別に印刷する必要があります(または、予約済みバッファーに個別に書き込み、1回のsys_write呼び出しを使用してバッファー全体を印刷します)。

于 2013-03-20T00:15:42.083 に答える