0

NASM を学び始めたばかりで、テキスト ファイル内の行列を含む最初のプログラムを実行しています。このファイルには N*N 行列が含まれており、最初の行には N が含まれ、他の行にはそれぞれ行列の 1 行が含まれています。より大きなタスクを完了するための作業を開始するために、ファイルを 1 行ずつ読み取り、各行をコンソールに出力するコードを借りてきました。

最初の行を読み取り、文字列から整数に変換し、それをカウンターとして使用するレジスタに移動してから、配列のその行数を出力するつもりです。N=7 の場合でも、ファイルの先頭行をいじって 3 とすると、3 行が出力されれば機能します。しかし、これはうまくいきませんでした。常に 1 行を出力するようにしました。これは、読み込んで int に変換した数値が正しく変換されなかったことを示唆しています。この数値を変換して出力しようとしたのですが、セグフォルトになってしまいビックリ!

Linux での NASM のコードは次のとおりです。

; this program demonstrates how to open files for reading
; It reads a text file line by line and displays it on the screen

extern fopen
extern fgets
extern fclose
extern printf
extern exit

global main

segment .data
readmode: db "r",0
filename: db "hw6_1.dat",0 ; filename to open
error1:   db "Cannot open file",10,0
format_1: db "%d",0

segment .bss
buflen:   equ 256         ; buffer length
buffer:   resd buflen     ; input buffer

segment .text
main: pusha
; OPENING FILE FOR READING  
push readmode       ; 1- push pointer to openmode   
push filename       ; 2- push pointer to filename
call fopen          ; fopen retuns a filehandle in eax
add esp, 8          ;   or 0 if it cannot open the file
cmp eax, 0          
jnz .L1             
push error1         ; report an error and exit
call printf
add esp, 4
jmp .L4

; READING FROM FILE     
.L1:  mov ebx, eax        ; save filepointer of opened file in ebx

; Get first line and pass to ecx
push ebx
push dword buflen
push buffer
call fgets
add esp, 12
cmp eax, 0
je .L3

;convert string -> numeric
push buffer
call parseInt
mov ecx, eax

.L2:  
;debug
push ecx
push format_1
call printf
add esp, 8

push ebx            ; 1- push filehandle for fgets
push dword buflen   ; 2- push max number of read chars
push buffer         ; 3- push pointer to text buffer
call fgets          ; get a line of text        
add esp, 12         ; clean up the stack
cmp eax, 0          ; eax=0 in case of error or EOF
je .L3
push buffer         ; output the read string
call printf
add esp, 4          ; clean up the stack
dec ecx
cmp ecx, 0
jg .L2

;CLOSING FILE  
.L3:  push ebx            ; push filehandle 
call fclose         ; close file
add esp, 4          ; clean up stack

.L4:  popa
call exit

parseInt:   
push ebp
mov ebp, esp
push ebx
push esi
mov esi, [ebp+8]        ; esi points to the string

xor eax, eax            ; clear the accumulator
.I1   cmp byte [esi], 0       ; end of string?
je .I2
mov ebx, 10
mul ebx                 ; eax *= 10
xor ebx, ebx
mov bl, [esi]           ; bl = character
sub bl, 48              ; ASCII conversion
add eax, ebx
inc esi
jmp .I1

.I2:   pop esi
pop ebx
pop ebp
ret 4

サンプル データ ファイルを以下に示します。これは私が使用していたものです。

4
2 45 16 22
17 21 67 29
45 67 97 35
68 34 90 72

これがどのように機能していないのか、私は本当に理解していません。整数に変換するコードは、デバッグに使用した出力用のコードと同様に、WORKING プログラムから借用したものです。

4

1 に答える 1