尝试将数组加倍以增加数组以添加更多元素。没有编译或运行时错误,但它不允许您在5之后输入更多元素我不确定是否数组大小根本没有加倍或发生了什么,因为您可以插入5个数字,然后输入将完成并打印统计数据。我需要它加倍阵列每次用户填充阵列,直到他们按下(ctrl d),然后它去输出统计数据。
%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, realloc
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
; check if the array is full, if so, double its size
cmp r15, ARRAY_SIZE
jl inputNotFull
; double the array size and copy the elements to the new array
mov rsi, [arrayPtr]
mov rdi, ARRAY_SIZE*2*ELEMENT_SIZE
call realloc
mov [arrayPtr], rax
mov rcx, [ARRAY_SIZE]
rep movsd
mov eax, ARRAY_SIZE
imul eax, 2
mov [ARRAY_SIZE], eax
; continue with the input
inputNotFull:
inc r15 ; O/w count another element & store it
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
dec rcx
jnz 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
我尝试增加rcx,因为这决定了它是否会跳回到inputLoop:以获得更多的输入,但随后它给出分段错误。
1条答案
按热度按时间kninwzqo1#
它不允许你在5之后输入更多的元素
这仅仅是因为 inputLoop 被告知进行5次迭代,之后它在 inputDone 中福尔斯。
本质上,你需要的是一个无限循环,它无条件地跳回到 inputLoop 的顶部。当然,在 scanf 返回EOF时,总是会保留已经可用的早期退出。
我试着增加rcx...但它给出了一个分段错误。
上面的问题实际上是一件好事,因为正如你所报告的,增加迭代次数会触发“分段错误”。这是由于调用 realloc 时没有遵循规则。地址在RDI中,新的总大小在RSI中;另外,如果 realloc 必须对分配进行物理重定位(大多数情况下它不必这样做),那么它将移动内容。您不需要重新做这件事,当然也不需要使用错误的寄存器。
我对你这部分节目的建议
我构建这个模型的前提是,数组中元素数量的动态调整应该遵循5 -〉10 -〉20 -〉40的顺序,并且除非绝对必要,否则不会执行任何更改(例如,当数组的大小仍然是5时接收到第6个输入,或者当数组的大小仍然是10时接收到第11个输入,等等):
请注意,我引入了一个新变量 arrayEnd,它保存指向数组后面的指针,类似于 arrayPtr 保存指向数组开头的指针。
提示:是否应该检查 calloc 和 realloc 是否成功返回(检查RAX)?