Write a program to count how many entries in an N-byte array are positive, negat
ID: 2268031 • Letter: W
Question
Write a program to count how many entries in an N-byte array are positive, negative, even, and/or odd. The array should be stored starting at memory location $100. The value of N should be set in your code using the assembly directive ‘EQU’. An entry is considered positive if its MSB is ‘0’ and negative if it’s ‘1’. An entry is considered even if its LSB is ‘0’ and odd if it’s ‘1’. The four count values should be stored at memory locations $00-$03 in the following order: negative count, positive count, even count, odd count. Your code instructions should be stored starting at memory location $B600 (EEPROM).
I am using MiniIDE and Buffalo Monitor to run and test the code.
This is what I have so far:
* data storage declaration
org $00 ; start at memory location $00
neg rmb 1 ; 1 byte reserved for negative count
pos rmb 1 ; 1 byte reserved for positive count
even rmb 1 ; 1 byte reserved for even count
odd rmb 1 ; 1 byte reserved for odd count
N equ 20 ; array count
org $100 ; start at memory location $100
array fcb
* program instruction
ldaa array ; set [A] to array[0]
ldab #1 ; initialize loop index to 1
loop ldx #array ; point X to array[0]
abx ; compute the address of array[i]
cmpa 0,X ; compare temp array max to the next element
bhs chkend
ldaa 0,X
chkend cmpb #N-1 ; compare loop index with loop limit
beq exit ; if loop counter = array count, exit
incb ; increment loop counter
bra loop ; branch up to 'loop'
exit staa neg ; stores the number of all negative numbers
staa pos ; stores the number of all positive numbers
staa even ; stores the number of all even numbers
staa odd ; stores the number of all odd numbers
swi
Thanks!
Explanation / Answer
section .rodata
word_array dw -1,2,-3,4
len equ $-word_array ; length in bytes. assembler constant, so we can mov reg, imm8/imm32 rather than loading it as data.
section .text
proc:
mov esi, word_array ; esi points to the array. In MASM, use OFFSET word_array
mov ecx, len/2 - 1 ; [esi + ecx*2] points to the last element
xor edx, edx ; non_neg_count = 0
countloop:
; cmp [esi + ecx*2], 0 ; This can't macro-fuse (memory and immediate operand). Also can't micro-fuse on SnB, because of a 2-reg addressing mode
movsx eax, word [esi + ecx*2] ; use a 2-reg addressing mode to save loop overhead, since this there's no ALU execution port component to this insn. It doesn't need to micro-fuse to be one uop
test eax, eax ; can macro-fuse with js
js isNegative
inc edx ; counting non-negative numbers
isNegative:
dec ecx ; can macro-fuse with jge, but probably won't unless alignment stops it from being decoded in the same cycle as the earlier test/js
jge countloop ; jge, not jnz, because we want ecx from [0 : len-1], rather than [1 : len]
; after the loop, ecx=-1, edx=non_neg_count
; neg_count = array_count - non_neg_count
mov eax, len/2
sub eax, edx ; eax = neg_count
ret ; return values in eax:edx
positive vs negative
section .rodata
word_array dw -1,2,0,-3,4
len equ $-word_array ; length in bytes. assembler constant, so we can mov reg, imm8/imm32 rather than loading it as data.
section .text
proc_pos_and_neg:
mov esi, word_array ; esi points to the array. In MASM, use OFFSET word_array
xor edx, edx ; pos_count = 0
xor eax, eax ; neg_count = 0
mov ebp, -1 ; constant to test with
lea edi, [esi + len] ; points one past the end of the array
xor ebx, ebx ; clear upper portion, because setcc r32 isn't available, only setcc r8 :(
countloop:
test bp, word [esi] ; test reg, mem can micro-fuse, but test mem, imm can't
setg bl ; 0 or 1, depending on array[i] > 0
lea edx, [edx + ebx] ; add without affecting flags
setl bl
add eax, ebx ; can clobber flags now
add esi, 2 ; extra loop overhead compared to the scan-backwards decrementing an index reg I used last time
cmp esi, edi
jb countloop ; loop while our pointer is below the pointer to one-past-the-end
ret ; neg_count in eax, pos_count in edx
another method
proc:
mov si, data ; si points to the data
mov cx, [len] ; cx gets the length of the data
shr cx,1 ; the length was in bytes, we want words
mov bx, 0
mov dx, cx
checkNext:
mov ax, [si]
text ax, ax ; alternatively: test ax, 8000h
js isNegative
inc bx ; counting positive numbers
isNegative:
add si, 2 ; moving to next word
loop checkNext ; decrease cx, jump if not 0
sub dx, bx ; bx has the positive numbers, dx - the negative ones
ret ; done
data dw -1,2,-3,4
len dw $-data
TO FIND EVEN AND ODD NUMBERS
MVI C,00
MVI D,00
MVI E,00
LXI H,4200
MOV B,M
INX H
LXI H,4200
MOV B,M
LABEL4:INX H
MOV A,M
CPI 00
JNZ LABEL1
INR C
JNZ LABEL2
LABEL1:RRC
JNZ LABEL3
INR D
JMP LABEL2
LABEL3:INR E
LABEL2:DCR B
JNZ LABEL4
INX H
MOV A,C
MOV M,A
INX H
MOV A,D
MOV M,A
INX H
MOV A,E
MOV M,A
HLT
SAMPLE OUTPUT
ADDRESS
DATA
INPUT/OUTPUT
4200
09
Input
4201
00
Input
4202
06
Input
4203
02
Input
4204
11
Input
4205
0A
Input
4206
0D
Input
4207
00
Input
4208
0F
Input
4209
10
Input
420A
02
Output
420B
04
Output
420C
03
Output
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.