简体   繁体   中英

Writing to address based on its value

I was given a task to write numbers from the relative address 10h numbers 0-255 in ascending order if the address is even and numbers from 0-255 in descending order if the adress is not even

then we had to sum up all the numbers from address 10h to 210h This is my code, I don't know why it doesn't work:

;Write into Address
MOV SI,10h
MOV AL,0d
MOV BX,255
MOV CX,255     

LOOP1:

TEST SI,00000001b   
jnz notzero
jz zero      

notzero: 
MOV [SI],BX
DEC BX
INC SI
LOOP LOOP1

zero:
MOV [SI],AL
INC SI 
INC AL
LOOP LOOP1

;Sum up address from 10h to 210h
MOV AL,0
MOV SI,10h
MOV cx,200  

Loop1:

ADD AL,[SI]
INC SI
LOOP Loop1  

I would use just AX for all your math.

MOV SI,10h
MOV AX,FF00h  ;Or mov ax,0xff00 or however it is written
MOV CX,255    ;One memory write before the loop, 255 writes from the loop

WRITE_512_BYTES:
MOV [SI],AX
DEC AH
INC AL
ADD SI,2
LOOP WRITE_512_BYES

;Sum up address from 10h to 210h
MOV AX,0
MOV BX,0
MOV SI,10h
MOV CX,511  ;One iteration before the loop, 511 loops, 512 bytes summed.

SUM_LOOP:
MOV BL, [SI]  ;populate lower byte of bx from memory
ADD AX, BX    ;BH guaranteed to still be 0 from earlier MOV
INC SI
LOOP SUM_LOOP  

Bugs that have been discussed in other comments: 1- BX versus BL. Even if you have the correct value in BX (say, 0005h), when you write BX to memory, you'll be writing both the 00 and the 05. In your code, you only want to write one byte. The code I have writes two bytes, but also adds two to SI.

2- Was pointed out, but it is unclear what memory "from 10h to 210h" is referring to. If you were told to check the values of the bytes "from 10h to 10h", you would assume you were checking one byte- an inclusive range, so 10h-10h+1=1. Likewise, 210h-10h+1 = 201h = 513 bytes. Since you are only writing 512 bytes, that's probably not correct. Your algorithm will populate bytes from 10h to 20Fh.

3- Was pointed out, but as you sum the numbers with

ADD AL,[SI]   

You will overflow your 8 bit register AL, because the sum of the numbers is too big for the 0-255 range.

4- As was pointed out, when LOOP runs out of cx to count with, it will continue with the next instruction underneath it. This means that your notzero case will begin executing the zero case. You could solve this with an unconditional jump, placed directly underneath the LOOP, to the sum section, which you'll need to label as such.

5- I don't know why you are getting an error with mov [si],bl. Are you sure it is typed correctly? That is a valid instruction.

Nits:

TEST SI,00000001b

This does in fact AND SI with 1 and set flags, but it is odd to specify 1 as the 8 bit value "00000001b". The actual comparison is done as 16 bits, 32 bits, or 64 bits, depending on what mode you are running in. Consider just comparing it to 1 (and letting the assembler zero extend the value) instead of writing it out partially as an 8 bit value.

2- When you are doing a compare for one of two exclusive branches, you could get away with just testing one of the cases. For instance, if you do the test and then do the

jz zero

You will conditionally jump to the zero case, and then you can just have the non-zero case without any further redirection: just eliminate the jnz instruction.

3- It would be kinda good to know where you are running this. In 16 bit DOS COM files, for instance, you would end up overwriting your own code when you wrote to bytes at 100h and above. I'm assuming that the memory addresses are safe for wherever you are writing this, because that was in your instructions.

Problems found in your code are commented with arrows ◄■■■ :

.model small
.stack 100h
.data
arr db 1024 dup (0)   ;◄■■■ BUFFER FOR THE NUMBERS.
.code
  mov ax, @data
  mov ds, ax

;Write into Address
MOV SI,10h
MOV AL,0d
MOV BL,255            ;◄■■■ BL, NOT BX, BECAUSE BX IS TWO BYTES.
MOV CX,255     

LOOP1:

TEST SI,00000001b   
jnz notzero
jz zero      

notzero: 
MOV [SI],BL          ;◄■■■ BX IS TWO BYTES, SO WE USE BL INSTEAD.
DEC BL               ;◄■■■ BL, NOT BX.
INC SI
LOOP LOOP1

zero:
MOV [SI],AL
INC SI 
INC AL
LOOP LOOP1

;Sum up address from 10h to 210h
MOV AX,0              ;◄■■■ AL IS TOO SMALL FOR THE SUM.
MOV SI,10h
MOV cx,200h           ;◄■■■ 200H, NOT 200.  
MOV BH,0              ;◄■■■ CLEAR BH TO USE BX.

Loop2:                ;◄■■■ "LOOP1" WAS ALREADY USED.
MOV BL,[SI]           ;◄■■■ EXTRACT ONE BYTE ONLY.
ADD AX,BX             ;◄■■■ BH WAS CLEARED, SO BX=BL.
INC SI
LOOP Loop2            ;◄■■■ "LOOP1" WAS ALREADY USED.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM