【问题标题】:NASM: adding numbers of the main diagonal in a tableNASM:在表格中添加主对角线的数字
【发布时间】:2013-10-01 15:30:40
【问题描述】:

我正在编写的程序旨在从文本文件中获取表格。表格的格式如下:表格是 NxN,第一行是数字 N。然后表格的每一行都包含在自己的行中。因此,该文件有 N + 1 行。

程序应该读入表格,并沿对角线从左上到右下抓取数字,然后将它们相加,将结果输出到屏幕。

目前,我正在研究一个程序,该程序将保存数字行的缓冲区以及用户希望检索的数字作为输入。目的是在 eax 中返回它。但是,此过程目前似乎会导致段错误。我查看了我的代码,这对我来说似乎很有意义。下面是一个示例表文件和我的源代码。

hw6_1.dat

5
2 45 16 22 4
17 21 67 29 65
45 67 97 35 87
68 34 90 72 7
77 15 105 3 66

hw6_1.asm

; 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",10,0
format_2: db "%s",10,0

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

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 buflen
push buffer
call fgets
add esp, 12
cmp eax, 0
je .L3

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

.L2:
push ecx

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
push dword 2
push buffer
call grabNum ;Get the 3rd number in the current line. Space delimited.

;do somehing with the number. For now, lets just output to screen.
push eax
push format_1
call printf
add esp, 8

pop ecx
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], 48       ; end of string?
jl .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


grabNum:

;This method will grab a specified number in a sequence.
;Ex: passed in is buffer and the number 4. The 4th number will be
;returned. It is assumed to be a space delimited buffer.

mov esi, [esp + 4]
mov ecx, [esp + 8]
dec ecx

.skipNum:
;for each number in ecx, advance past a number in esi.
;this is done by decrementing ecx each time a "non-digit" is detected.
;Since the buffer is known to be space delimted, this is a valid strategy.
cmp ecx, 0
je .doneSkipping

cmp byte [esi], 48
jl .numSkipped
cmp byte [esi], 57
jg .numSkipped

inc esi

jmp .skipNum

.numSkipped:

inc esi
dec ecx
jmp .skipNum


.doneSkipping:
;now we grab the number from buffer in its ASCII form. We place it in tempBuff,
;and call parseInt. This should leave the number in integer form waiting in eax
;after the end of the grabNum call.

cmp byte [esi + 1 * ecx], 48
jl .retGrab
cmp byte [esi + 1 * ecx], 57
jg .retGrab
mov ebx, [esi + 1 * ecx]
mov [tempBuff + 1 * ecx], ebx
inc ecx
jmp .doneSkipping



.retGrab:
mov [tempBuff + 1 * ecx], byte 0
push tempBuff
call parseInt

ret 8

确切地说,程序打印出“45”,即第一行中的第二个数字,正如我目前所打算的那样,但似乎在第二行可以输出到屏幕之前抛出了段错误。

【问题讨论】:

  • 解决了!看来,通过使用 ebx 作为过程中某些数据的临时保存者,我正在擦除其对主过程的值,即文件句柄!由于这个值是错误的,它可能会在尝试从文件中读取下一行时抛出段错误。使用 eax 作为临时信息持有者可以解决问题!
  • 更改了代码以反映我当前的工作代码!感谢阅读。
  • 我撤消了您的更改。不要使用修复程序修改原始问题。你创建一个答案(你做了)并说明你改变了哪些行。这样,当将来有人来看这个问题和答案时,问题中的代码有错误,答案有修复。此外,如果您回答您的问题并将其标记为已接受,请不要在问题标题中添加solved。如果有接受的答案,Stackoverflow 会将问题标记为已解决。如果您觉得问题和答案对未来的读者没有价值,那么我建议您删除该问题。

标签: string matrix ascii nasm


【解决方案1】:

不小心使用了 EBX 寄存器来保存一些临时数据。这破坏了文件句柄并导致了段错误。而是使用 EAX 来保存此数据,从而解决了问题!

为了解决这个问题,我修改了这两行:

mov ebx, [esi + 1 * ecx] 
mov [tempBuff + 1 * ecx], ebx

成为:

mov eax, [esi + 1 * ecx]
mov [tempBuff + 1 * ecx], eax

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    相关资源
    最近更新 更多