I am trying to write an assembly program that uses a procedure to populate an array with values 1-100. The code that I have so far is as follows:
jmp main
first100 dw 100 dup (?)
main:
call prepare
call populate
mov ax, first100[0]
call putDec
mov ah, 04c
int 021
include ioProcs.inc
prepare:
mov ax, 1
mov bx, 0
mov cx, 100
ret
populate:
mov first100[bx], ax
inc ax
inc bx
loop populate
ret
However, the first value in the array first100 turns into 513 as opposed to 1. It is probably something simple, but where am I messing up?
Thank you much for your time.
As #Jester mentioned you need to increment bx by two bytes in the populate loop.
You are creating an array of type dw, that is a word. It has a size of two bytes.
Related
IDEAL
MODEL small
STACK 100h
jumps
p186
DATASEG
array dw 312, 340, 311, 300
CODESEG
proc example
pusha
mov al ,4 ;number of elements in array
mov bl, 0 ;index
label1:
mov cx, [array + bx] ;here, every second element ch and cl are swapped
inc bl
cmp bl, al
jb label1
popa
ret
endp example
start:
mov ax, #data
mov ds, ax
call example
exit:
mov ax, 4c00h
int 21h
END start
In my assembly code, cx is okay in the 1st and 3rd iterations but in the 2nd and 4th ones for some reason cl and ch swapped their values with each other. I'm really overwhelmed with this and I would appreciate some help, thanks!
The elements of array are words, 2 bytes each, but you only increment your index bx by 1 on each iteration of your loop. Addresses on x86 are in units of bytes, so on the next loop iteration, you load from the middle of the word, and you end up with one byte from one element and another byte from the other.
Probably simplest to do everything in terms of bytes, instead of elements. (In 32- or 64-bit code you could use the scale addressing mode, mov cx, [array+ebx*2], and then keep counting ebx in elements, but that's not available in 16-bit real mode.)
Also, the high half of bx is uninitialized. It's probably best to just use 16-bit values for your indices.
I'd rewrite as (untested):
CODESEG
proc example
pusha
mov ax, 4*2 ;number of bytes in array
mov bx, 0 ;index
label1:
mov cx, [array + bx]
; presumably do something with cx here
add bx, 2
cmp bx, ax
jb label1
popa
ret
endp example
I'm learning x86 assembly and I'm trying to write a program that reads a number n (2 digits) from user input and iterate n times.
I've tried many ways but I get an infinite loop or segment fault.
input:
push msgInputQty
call printf
add esp, 4
push quantity
call gets
add esp, 4
mov ecx, 2
mov eax, 0
mov ebx, 0
mov edi, 0
mov dl, 10
transform:
mul dl
mov ebx, 0
mov bl, byte[quantity+edi]
sub bl, 30h
add eax, ebx
inc edi
loop transform
mov ecx, eax
printNTimes:
push msgDig
call printf
add esp, 4
loop printNTimes
I'd like to save in ecx and iterate n times this number
Your ecx register is being blown away by the call to printf.
ecx is a volatile register in some calling conventions and its likely that your loop is being corrupted by what printf is leaving in there.
To begin with, I would follow Raymond's advice in the comment attached to your original question and attach a debugger to witness this behaviour for yourself.
As for a solution, you can try preserving ecx and restoring it after the call to see the difference:
; for example
mov edi,ecx
call printf
mov ecx,edi
There may be more issues here (hard to know for sure since your code is incomplete ... but things like your stack allocations that don't appear to be for any reason are interesting) - but that is a good place to start.
Peter has left a comment under my answer to point out that you could remove the issue and optimize my solution by just not using ecx for your loop at all and instead do it manually, making your code change:
mov edi, eax
printNTimes:
push msgDig
call printf
add esp, 4
dec edi
jnz printNTimes
I'm trying to take an array, add all the values in it, and then display them. Unfortunately for me, even though the following code builds, the output doesn't return the value which I am expecting.
For instance, one time when I ran it, I got
-2112902102
and another time I got
-1280521519
I'm assuming there's some sort of logic to that, but it doesn't exactly help me.
INCLUDE Irvine32.inc
.386
.stack 4096
ExitProcess proto,dwExitCode:dword
.data
array SBYTE 26, -81, -104, -57
total_sum SWORD ?
.code
main proc
mov esi, OFFSET array
mov ecx, LENGTHOF array
mov total_sum, 0
mov ebp,0
L1:
add ebp, [esi]
inc esi
loop L1
mov edx, ebp
call WriteInt
invoke ExitProcess,0
main endp
end main
And yes, I know that total_sum isn't doing anything at this point, but I first want to figure the rest out before implementing total_sum.
As you have been hinted, the problem is that you add dwords instead of bytes. The simple solution is to sign extend the byte into a temporary register before summing. That is replace this:
add ebp, [esi]
With:
movsx edx, byte ptr [esi]
add ebp, edx
And of course for printing you need to use eax, so change mov edx, ebp to mov eax, ebp. Or you could just use that to do the summing up directly.
I've a problem in assembly language that I want to make loop for sum element of an array. Suppose an array contains 10,20,30,40,50,60,70,80,90,100 I have to sum all elements of the array by loop... How can I do this?
I'm trying this:
.MODEL SMALL
.STACK 100H
.DATA
W DW 10,20,30,40,50,60,70,80,90,100
.CODE
MAIN PROC
MOV AX, #data
MOV DS, AX
XOR AX, AX
XOR BX, BX
MOV CX, 10
ADDNOS:
ADD AX, W [BX]
ADD BX, 2
LOOP ADDNOS
;this for display
MOV DX, AX
MOV AH,2
INT 21H
MOV AH, 4CH
INT 21H
MAIN ENDP
END MAIN
but something wrong in display that print from ascii (&).
EDIT: Updated answer since the code in the question has been changed:
INT 21h / AH=2 prints a single character (note that the integer 1 and the character '1' are different values).
The sum of the elements in your array is 550, which requires 3 characters to print. The way to solve that is to write a routine that converts the value 550 to the string "550", and then use INT 21h / AH=9 to print that string. How you'd go about doing that has been asked several times before on StackOverflow; see e.g. this question and the answers to it.
This is my answer for the original question
For future questions, note that "but something wrong" is a terrible problem description. You should explain precisely in what way the code isn't behaving the way you intended.
That said, there are a number of problems with your code:
Here you're initializing CX to the first value in x. Actually, since the elements in x are bytes (because you used DB) and CX is a word (two bytes) you'll get CX = 301h (which is 769 in decimal):
MOV CX, x
Here you're simply moving the first element of x into BX over and over, instead of doing an addition. And again, x contains bytes while BX is a word register.
top: MOV BX, [x]
The loop instruction decrements CX by 1 and jumps to the given label if CX != 0. By incrementing CX before the loop you're creating an infinite loop. Also, the CMP is useless (and I'm not sure why you're comparing against 7 since x only has 5 elements):
INC CX
CMP CX, 7
loop top
This will only work for values in the range 0-9. If the sum is >=10 it will require multiple characters. See e.g. this answer for an example of how to convert a multi-digit number to a string that can be printed. Also, you're writing a word-sized register to a byte variable:
ADD BX, '0'
MOV [sum], BX
Here I'm a bit lost at what you're trying to do. If you wanted to write a single character to STDOUT you should use INT 21h / AH = 2 / DL = character. Note that MOV AX,4 sets AH=0 and AL=4. Also, you should end your program with INT 21h / AX = 4C00h:
display_:
MOV DX,1
MOV CX, sum
MOV BX, 1
MOV AX,4
INT 21h
MOV AX, 1
INT 21h
I suspect that there is an error in the code following the top label.
You do MOV BX, [x] but I think there you should sum the item pointed by CX with what currently is in BX (that seems to store the sum). So substitute the move instruction with:
ADD BX, [CX]
The program must calculate the following:
in VP array , each index will have the value of Multiplying V1[INDEX] WITH V2[INDEX]
in VPROD array , the program ADDS all the Values of Array VP
Example:
VP = { V1[0]*V2[0] , V1[1]*V2[1] , V1[2]*V2[2] , V1[3]*V2[3] ,V1[4]*V2[4] }
VPROD = { VP[0] + VP[1] + VP[2] + VP[3] + VP[4] }
The problem is that when the result is bigger than 16 bits (a word), it does not give the right results. But when the result is smaller than 16 bits, it gives the right result.
I thought about Carry and fixed my code, but still it gives me bad results.
My code:
dseg segment
v1 DW 255,5,255,9,21
v2 DW 4,4,255,13,5
vprod DW 10 DUP (0)
vp DW 10 DUP (?)
N DB 5
dseg ends
sseg segment stack
dw 100h dup(?)
sseg ends
cseg segment
assume ds:dseg,cs:cseg,ss:sseg
start: mov ax,dseg
MOV DS,AX
MOV SI,0
MOV CX,0
MOV CL,N
MOV DI, 0
LOVP: MOV AX,v1[si]
MUL v2[si]
MOV vp[di],AX
MOV vp[di+2],DX
ADD SI,2
ADD DI,4
LOOP LOVP
MOV CX,0
MOV CL,N
MOV SI,0
MOV DI,0
LOVPROD: MOV AX,vp[SI]
ADD vprod[DI],AX
ADC VPROD[DI+2],0
ADD SI,2
LOOP LOVPROD
SOF:
mov ah,4ch
int 21h
cseg ends
end start
Since you are getting a 32 bit result from the multiply, you should use 4 bytes for every element of the vp array. You will need to use a separate index for that, and of course store the high word at offset +2 instead of +1. For the summation part, you should add up both low and high words.
Fixed code for the multiplication could look like:
MOV DI, 0
LOVP: MOV AX,v1[si]
MUL v2[si]
MOV vp[di],AX
MOV vp[di+2],DX
ADD SI,2
ADD DI,4
LOOP LOVP
I trust you can do the summation yourself, using ADD and ADC.
UPDATE:
Since your post says you want to sum the vp array, I don't see why you expect the result in another array (vprod). The sum is a scalar value, do something like:
MOV SI, 0
MOV AX, 0
MOV DX, 0
LOVPROD: ADD AX,vp[SI]
ADC DX,vp[SI+2]
ADD SI,4
LOOP LOVPROD
The result will be in DX:AX
Also, for the LOOP to work properly, you should put the number of iterations into CX, not 0 as you are doing.