我已经尝试解决这个问题 5 个小时了。我试图得到它,以便在将 5 个元素输入数组后,数组加倍并将旧元素复制到新元素中并继续直到你停止然后它输出统计信息,出于某种原因在输入 5 个数字后我只是得到分段错误
%define ARRAY_SIZE 5
%define ELEMENT_SIZE 4
%define EOF -1
segment .data
inputPrompt: db "Enter int value (ctrl-d to stop): ",0
intFormat: db "%d",0
output: db "Array[%d] = %d",10,0
dbout: db 10, 10,"[%d]",10,10,0 ; This is just for debugging output
newline: db 10,0 ; For whenever we need a newline
numElements: db "Number of elements: %d",10,0
outputSum: db "sum of elements: %d",10,0
minValue: db "Min value: %d",10,0
maxValue: db "Max value: %d",10,0
segment .bss
arrayPtr: resq 1 ; pointer to our array
intInput: resd 1
segment .text
global asm_main
extern printf, scanf, calloc
createNewArray:
mov rdi, [arrayPtr]
mov rsi, ARRAY_SIZE
add rsi, rsi ; Double the array size
mov rdx, ELEMENT_SIZE
call calloc
mov rbx, [arrayPtr] ; Move the old array elements to the new array
mov rcx, ARRAY_SIZE
cld
rep movsd
mov [arrayPtr], rax ; Save the new array pointer
ret
asm_main:
enter 0,0
;; Get memory for our array
;; Give calloc() number of element and element size
;; and calloc returns a pointer to zerioized memory
mov rdi, ARRAY_SIZE
mov rsi, ELEMENT_SIZE
call calloc
mov [arrayPtr], rax
mov rdi, [arrayPtr] ; Will use RDI and stosd to write the array
mov rcx, ARRAY_SIZE
mov r15, 0 ; R15 counts how many elements in our array
cld
inputLoop:
push rcx ; Save RCX and RDI across printf/scanf calls
push rdi
mov rdi, inputPrompt
call printf
mov rdi, intFormat
mov rsi, intInput
call scanf
cmp eax, EOF ; Did scanf() return -1 (didn't read anything?)
je inputDone
inc r15 ; O/w count another element & store it
cmp r15, ARRAY_SIZE ; Check if we've filled up the current array
jl arrayNotFull ; O/w, create a new array
call createNewArray
mov rdi, [arrayPtr] ; Update the pointers and sizes
mov rcx, r15
arrayNotFull:
xor rax, rax ; Clear out RAX for stosd to write array to mem
mov eax, [intInput]
pop rdi ; Restore RDI for stosd
stosd
pop rcx ; Restore RCS for loop instruction
loop inputLoop
inputDone: ; Let's get ready to print
mov rdi, newline
call printf
mov rsi, [arrayPtr] ; Will use RSI and lodsd to read the array
mov rcx, r15 ; Store actual array size to RCX
mov rbx, 0
cld
printLoop:
xor rax, rax
xor rdx, rdx
lodsd
push rcx ; Save RCX and RSI across printf call
push rsi
mov rdi, output
mov rsi, rbx
movsx rdx, eax
call printf
inc rbx
pop rsi ; Restore RCX and RSI
pop rcx
loop printLoop
je printStats
printStats:
mov rdi, newline
call printf
mov rdi, numElements
mov rsi, r15
call printf
mov rax, 0 ; Initialize the sum to zero
mov rsi, [arrayPtr] ; Get the address of the array
mov rcx, r15 ; Store actual array size to RCX
cld
xor rdx, rdx ; Clear out RDX for the first add instruction
mov rax, 0 ; Initialize the sum to zero
mov rsi, [arrayPtr] ; Get the address of the array
mov rcx, r15 ; Store actual array size to RCX
cld
sumLoop:
lodsd ; Load the next element of the array into EAX
add rax, r8 ; Add the current sum to EAX
mov r8, rax ; Store the updated sum in R8
loop sumLoop
mov rdi, outputSum
mov rsi, r8
call printf
; Find the minimum value in the array
mov rax, [arrayPtr] ; Load the base address of the array into RAX
mov ebx, [rax] ; Load the first element of the array into EBX
mov rcx, r15 ; Loop counter will be the number of elements
dec rcx ; Decrement RCX since we've already loaded the first element
mov rsi, [rax] ; Initialize RSI to the first element
loopStart:
add rax, ELEMENT_SIZE ; Move the pointer to the next element
cmp [rax], ebx ; Compare the value at the current pointer to the minimum value
jge loopEnd ; If the value is greater than or equal to the minimum, skip to the end of the loop
mov ebx, [rax] ; Otherwise, update the minimum value
mov rsi, rax ; and store the address of the minimum value in RSI
loopEnd:
loop loopStart ; Repeat for the remaining elements of the array
mov rdi, minValue
mov rsi, rbx
call printf
; Find the maximum value in the array
mov rax, [arrayPtr] ; Load the base address of the array into RAX
mov ebx, [rax] ; Load the first element of the array into EBX
mov rcx, r15 ; Loop counter will be the number of elements
dec rcx ; Decrement RCX since we've already loaded the first element
mov rsi, [rax] ; Initialize RSI to the first element
loopStartd:
add rax, ELEMENT_SIZE ; Move the pointer to the next element
cmp [rax], ebx ; Compare the value at the current pointer to the maximum value
jle loopEndd ; If the value is less than or equal to the maximum, skip to the end of the loop
mov ebx, [rax] ; O/w, update the maximum value to the current value
mov rsi, rax ; Store the address of the current maximum value
loopEndd:
loop loopStartd
mov rdi, maxValue
mov rsi, rbx
call printf
mov rax, 0
leave
ret
我试图保存新的数组指针 [arrayPtr],rax 但它似乎没有做任何事情或者我做错了什么,任何帮助都会很棒。
calloc 是如何工作的?寄存器的使用方式不一致。
第一次(在main)你像这样使用它:
mov rdi, ARRAY_SIZE mov rsi, ELEMENT_SIZE call calloc ; -> RAX
但是第二次(在 createNewArray 中)你像这样使用它:
mov rdi, [arrayPtr] mov rsi, ARRAY_SIZE add rsi, rsi ; Double the array size mov rdx, ELEMENT_SIZE call calloc ; -> RAX
接下来的
rep movsd
既没有给出合适的RSI也没有RDI。 segmentation fault的原因...
mov rbx, [arrayPtr] ; Move the old array elements to the new array mov rcx, ARRAY_SIZE cld rep movsd mov [arrayPtr], rax ; Save the new array pointer
在inputLoop中,您甚至在将第五个数组元素存储在第一个数组中之前就调用了createNewArray。这是您上述
rep movsd
无法正常运行的另一个原因。如果你知道你无论如何都要复制数组,为什么不在 main 中分配两倍的内存,然后同时存储到两个数组:
mov eax, [intInput]
pop rdi ; Restore RDI for stosd
mov [rdi + ELEMENT_SIZE * ARRAYSIZE], eax ; Store in 2nd array
stosd ; Store in 1st array