untio 36 Light Poster

Hi,
I think that your code is for a linux system. If I am right, you can read this:
http://board.flatassembler.net/topic.php?t=5361
It seems that at the program start the arguments are in the stack:
[esp] argc.
[esp + 4] argv[0]
[esp + 8] argv[1]
...
This, of course, if you program for 32 bits.

Bon courage.

untio 36 Light Poster

May be you may compare your code with this one:

#include<stdio.h>
int main()
{
        char arg[50];
        int c;
        int count=0;
        FILE *fp;
        printf("Name of the file:");
        scanf("%s",arg);
        fp=fopen(arg,"wt");
        printf("\t\t%s",arg);
        printf("Input the text into the file\n");
        printf("Press Ctrl+Z and Return on windows to the stop\n");
        while((c=getchar())!=EOF)
        {
                fputc(c, fp);
                count++;
        }
        fclose(fp);
        return 0; 
}

You will note some important diferences.

untio 36 Light Poster

Hi,
1. First of all, I advice you calling finit.
2. May be you must set the fpu control word.
3. Suposse you have a real number on st(0)
4. To divide it by an integer you need the address of the integer not the value in a register. You need the integer in memory -or on the stack-.
5. If ebx points to the four bytes of the integer, simply:
fidiv dword ptr [ebx] ;This is writen with masm sintax.
6. The value on st(0) will disapear and will be replaced with the result.

Cheers.

untio 36 Light Poster

My mother, what a strange code.
This could be done:
1. Moving zero to st0.
2. Pointing ebx to the first real.
3. Looping adding with: fadd [ebx] indicating the size of your real number (may be qword) and adding to ebx the size of your real (may be 8) and testing if the loop must end, may be 'dec edi jnz theloop'.
4. Getting the value of st0 as real 'fst'.
It is good to init the fpu with: finit and may be set the control word.
I can not test the code without the required routines, but I believe that there is too much push and pop.
Cheers.

untio 36 Light Poster

Hi,
In the x86 processors it is not possible to do an operation between two adresses of memory. Simply it is impossible to copy directly from memory to memory. You need to copy to a register and copy the content of the register to the target address.
Cheers.

untio 36 Light Poster

Hi,
A correction to my code:
You can erase:
movl %ebp, %esp
We are not using stack local space. esp is not modified.

Cheers.

untio 36 Light Poster

Hi,
I doubt between two options, but I put the shortest one. Try the next code:

.global _my_strlen

_my_strlen:

pushl %ebp
movl %esp, %ebp

movl 8(%ebp), %edx
movl $0xFFFFFFFF, %eax

loop:

inc %eax
cmpb $0, (%edx , %eax)

jne loop

movl %ebp, %esp
popl %ebp
ret

The other solution is increment edx and not to use eax in the comparison. It can be timed, but I think this code is not so important.

Cheers.

untio 36 Light Poster

Hi,
Look at:
http://www.scalprum.eu/cdecl_and_stdcall_calling_conventions.html
or look at:
http://en.wikipedia.org/wiki/X86_calling_conventions
or at:
http://www.hackcraft.net/cpp/MSCallingConventions/
Who is wrong?.
Another comment is that string opcodes are slower than a well optimized algoritm. Which is not the reference code.
The problem of restoring ebx can be solved using another register, maybe edx.

Cheers.

Ancient Dragon commented: Yes, I was incorrect +36
untio 36 Light Poster

Hi,
'je exit' exits from the loop when bx is equal to zero, je acts like jz. May be you want to write:
inc bx
cmp eax, -1
Because in you code 'cmp eax, -1' has no effect.
Cheers.

untio 36 Light Poster

Hi once more,
Another suggestion is that you must restore ebx before exiting. It must return with the same value that it entered.
You are using the cdecl calling convention and its rules apply. Take a look at:
http://www.scalprum.eu/cdecl_and_stdcall_calling_conventions.html
Cheers.

untio 36 Light Poster

Hi,
I give you an advice:
If your string is of type char (1 byte), why are you comparing double words (cmpl), may be you need cmpb (byte).
Another one:
You increment ebx before comparing the first character.
I hope that this can be useful.

untio 36 Light Poster

Hi,
I have rewriten the printing of numbers.
Now it is correct. Try this code:

.model small


threshold equ 5
count equ 24

.stack 2048





.data
	prompt1 db "Your array: $"
	mystring db 40 dup("a"), '$'

	thr_prompt db 'Your threshold number is: $'
	msg db 'The number of elements of your array is:$'
	newline db 10, 13, '$'
	array db 1,2,3,4,5,6, 7, 8, 9 , 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 101;declare a byte array
	len equ $-array ;"$" means current address. 

	num db 0

	


.code 

start:
	mov ax,@data ;initialise data segment
	mov ds,ax
	xor	ch,ch		;initialize counter
	mov	cl,count	
	xor	bx,bx		;initialize index register	
display_msg:
	mov dx, offset prompt1
	call printstring
	
key:	
	mov	dl,array[bx]	;store the number at the array
	call printnumber
	inc	bl		;increment index register
	dec	cl		;decrement counter
	jnz	key
    
	xor	ch,ch		;initialize counter
	mov	cl,count
	xor	bx,bx		;initialize index register	
elements:
	call printnewline
	mov dx, offset msg
	call printstring
	mov dl,20h
	call printchar
	mov dl,len
	call printnumber
	call printnewline
	mov dx, offset thr_prompt
	call printstring
	mov dl,20h
	call printchar
	mov dl, threshold
    call printnumber
	call printnewline
daniweb:	
	mov dl,array[bx]
	cmp dl,threshold
	jae bigger
	call printnumber
bigger:
	inc bx
	dec cl
	jnz daniweb
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
check_even:
	call printnewline
	xor bx, bx
	;YOU DO NOT USE SI.
	;mov si,offset array
	mov cl, count
	xor dh, dh
	xor ax, ax
	xor si, si
again:
	;YOU ARE GETING WORDS (2 BYTES) BECAUSE YOU ARE USING AX. AX IS A …
untio 36 Light Poster

Hi,
What do you think about the next code:

stk	segment	stack
	db	128 DUP(?)
stk	ends
;

data segment
	prompt1 db 'Your array: $'
	array db 1,2,3,4,5,6, 7, 8, 9 , 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24;declare a byte array
	len equ $-array ;"$" means current address. 
	thr_prompt db 'Your threshold number is: $'
	msg db 'The number of elements of your array is:$'
	newline db 10, 13, '$'
	threshold equ 5
	num db 0
	count equ 24
	
data ends

code segment
assume cs:code, ds:data, ss:stk

start:
	mov ax,data ;initialise data segment
	mov ds,ax
	xor	ch,ch		;initialize counter
	mov	cl,count	
	xor	bx,bx		;initialize index register	
display_msg:
	lea dx, prompt1
	call printstring
key:	
	mov	dl,array[bx]	;store the number at the array
	call printnumber
	inc	bl		;increment index register
	dec	cl		;decrement counter
	jnz	key
    
;done1: 
	xor	ch,ch		;initialize counter
	mov	cl,count
	xor	bx,bx		;initialize index register	
elements:
	call printnewline
	mov dx, offset msg
	call printstring
	mov dl,20h
	call printchar
	mov dl,len
	call printnumber
	call printnewline
	mov dx, offset thr_prompt
	call printstring
	mov dl,20h
	call printchar
	mov dl, threshold
    call printnumber
	call printnewline
daniweb:	
	mov dl,array[bx]
	cmp dl,threshold
	jae bigger
	call printnumber
bigger:
	inc bx
	dec cl
	jnz daniweb
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
check_even:
	call printnewline
	xor bx, bx
	;YOU DO NOT USE SI.
	;mov si,offset array
	mov cl, count
	xor dh, dh
	xor ax, ax
	xor si, si
again:
	;YOU ARE GETING WORDS (2 BYTES) BECAUSE YOU ARE USING AX. AX IS …
untio 36 Light Poster

Hi,
Look at this code. It compiles in masm:

stk	segment	stack
	db	128 DUP(?)
stk	ends
;

data segment
	prompt1 db 'Your array: $'
	array db 1,2,3,4,5,6 ;declare a byte array
	len equ $-array ;"$" means current address. 
	thr_prompt db 'Your threshold number is: $'
	msg db 'The number of elements of your array is:$'
	newline db 10, 13, '$'
	threshold equ 5
	num db 0
	count equ 6
	
data ends

code segment
assume cs:code, ds:data, ss:stk

start:
	mov ax,data ;initialise data segment
	mov ds,ax
	xor	ch,ch		;initialize counter
	mov	cl,count	
	xor	bx,bx		;initialize index register	
display_msg:
	lea dx, prompt1
	call printstring
key:	
	mov	dl,array[bx]	;store the number at the array
	call printnumber
	inc	bl		;increment index register
	dec	cl		;decrement counter
	jnz	key
    
;done1: 
	xor	ch,ch		;initialize counter
	mov	cl,count
	xor	bx,bx		;initialize index register	
elements:
	call printnewline
	mov dx, offset msg
	call printstring
	mov dl,20h
	call printchar
	mov dl,len
	call printnumber
	call printnewline
	mov dx, offset thr_prompt
	call printstring
	mov dl,20h
	call printchar
	mov dl, threshold
    call printnumber
	call printnewline
daniweb:	
	mov dl,array[bx]
	cmp dl,threshold
	jae bigger
	call printnumber
bigger:
	inc bx
	dec cl
	jnz daniweb
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
check_even:
	call printnewline
	xor bx, bx
	;YOU DO NOT USE SI.
	;mov si,offset array
	mov cl, count
	xor dh, dh
	xor ax, ax
	xor si, si
again:
	;YOU ARE GETING WORDS (2 BYTES) BECAUSE YOU ARE USING AX. AX IS A 16 BITS REGISTER.
	;mov ax,array[bx]
	;ROR MODIFIES THE REGISTER.
	;ror ax,1 
	mov dl, array[si]
	;TEST PERFORMS AN …
untio 36 Light Poster

Hi, you are a good programmer. This kind of bugs are the worst ones. The tipyng ones
Look at the next code:

stk	segment	stack
	db	128 DUP(?)
stk	ends
;

data segment
	prompt1 db 'Your array: $'
	array db 1,2,3,4,5,6 ;declare a byte array
	len equ $-array ;"$" means current address. 
	thr_prompt db 'Your threshold number is: $'
	msg db 'The number of elements of your array is:$'
	threshold equ 5
	num db 0
	count equ 6
	
data ends

code segment
assume cs:code, ds:data, ss:stk

start:
	mov ax,data ;initialise data segment
	mov ds,ax
	xor	ch,ch		;initialize counter
	mov	cl,count	
	xor	bx,bx		;initialize index register	
	xor dx,dx
	mov si,offset array
	

display_msg:
	lea dx, prompt1
	mov ah,09
	int 21h
	

	;WHY DO YOU WRITE THIS JUMP. key IS THE ADDRESS OF THE NEXT INSTRUCTION.	
	jmp key;REMOVE THIS LINE.
	;REMOVE IT
	
key:	
	mov	al,array[bx]	;store the number at the array
	mov	ah,2		;display the number at the screen
	mov	dl,al
	add dl,30h
	int	21h
	inc	bl		;increment index register
	dec	cl		;decrement counter
	jnz	key

done1: 
	xor	ch,ch		;initialize counter
	mov	cl,count
	xor	bx,bx		;initialize index register	
	mov	ah,2		;printing a space
	mov	dl,20h
	int 21h
		

elements:
	mov dl,10d ;display line
	mov ah,2h
	int 21h
	
	mov dl,65d ;display line
	mov ah,2h
	int 21h	
	
	mov ah,09
	mov dx, offset msg
	int 21h
	mov ah,2 ;sent space
	mov dl,01h
	mov dl,20h
	int 21h
	mov dl,len
	add dl,30h ;convert the ascii value to integer number
	mov ah,2
	int 21h

thr_msg:
	mov dl,10d ;display line
	mov …
untio 36 Light Poster

Hi,
You need to point bx to the start of the array.
xor bx, bx
is a faster version of:
mov bx, 0

bx must point to the start of the array. In masm you should use:

.data
array db 1,2,3,4,5,6
etc,

.code
mov ax, @data ;
mov ds, ax;
;You need to specify the data segment and offset. Now the data segment is in ds

.etc,

mov bx, offset array

and if this does not work:

lea bx, array ; (load efective address) Load the offset of the array inside the ds segment inside bx

Now in the pair: ds:bx is the adress of the first element of the array.
is a pointer to the array.

mov al, ds:[bx] ; will copy the first value inside the array to al

mov al, ds:[bx + 2]; will copy the third value.

The reason to use [bx] and not bx is because we use bx as a pointer. It contains the offset of array.

If inside bx there is a zero and you try something like:

mov register, [bx] ; Access violation error.

and if you try:

mov register, bx; and bx contains zero, the target register will contain zero.

And of course, I know more than needed to write your program and much more complex programs, but are you who are learning.

I …

untio 36 Light Poster

I was confused with the criteria. I do not remembered it.
Change jne to jae for unsigned numbers or to jge for signed numbers.

untio 36 Light Poster

Hi,
The two error messages are because you are working with elements of two diferent sizes.
mov bx, al ;bx -> 16 bits. al -> 8 bits.
cmp al, ax ; al -> 8 bits. ax -> 16 bits.

I hope that this can be useful.

Rewrite:

I have no tested the next code because I am not with my computer. Please, correct the stuff if needed.

lea bx, array
mov al, value
mov di, 0
mov dx, itemsnumber
label1:
cmp al, [bx + di]
jne label2
call printvalue
label2:
inc di
dec dx
jnz label1

untio 36 Light Poster

If you have, for instance, in eax the value 2 and you add 0 to eax, eax will contain 2. Add zero has no effect.
If you want a register with a zero value, you can do it with 'mov eax, 0' or, as prefered by some programers: 'xor eax, eax'.

untio 36 Light Poster

Hi,
You can remove lines from 25 to 29 without any doubt.

untio 36 Light Poster

Hi,
What is the reason to add zero to the registers. This has no effect. Why?.
The rest of the code is very good.

Best regards

untio 36 Light Poster

Hi,
You need a complete course on assembly language.
You try to declare a variable inside the text section. Text section is for machine instructions.
If you must reserve space for variables, you can achieve it in:
data section if the variable is initialized.
bss section if the variable in not initialized.
In this case data will reside in the bss section. Do reserve space in the bss section, nasm have this method:

[section .bss]
	 K : resd 1
	 D : resd 1

before the text section
The 'd' means dword, four bytes.
In assembly language there is not a ':=' operator. If you need to assign a value, you can do it like 'mov eax, ebx'. It will copy the value inside ebx into eax.
Another big error is in the imul operands. imul multiplies with sign the operand by eax and put the result in edx:eax.

mov edx, 0
mov eax, 2
mov ebx, 3
imul ebx

edx contains 0 and eax contains 6.
A bigger error is:

sub K, 1

In x86 it is not possible to operate with two places in memory. The assembler will complain with a message: invalid combination of opcode and operands.
You must write something like this:

mov eax, K
sub eax, 1
mov K, eax

And, finally, do you wish to try this code - with nasm syntax-:

;;
	;; Register usage:
	;; EAX Sum
	;; ECX Original value of …
untio 36 Light Poster

Hi to all,
This is a question that arises many times.
In another place, I have answered this question. You can see the answer at:
http://www.programmingforums.org/thread30456.html

As you can see, you divide the number by 10 and save the remainder in the stack and increment the counter. You must do this repeatedly until the number becomes lower than 10. You push it another time and increment the counter. After that, the numbers will exit from the stack in the correct way. In the example I convert them to an string.
I hope that this can be useful.

untio 36 Light Poster

Hi,
The problem is that 'add si, 1' modifies the flags. You can test if bh is equal to zero after adding 1 to si and your code will work right.

;cmp bh, 0 - Remove this line
add di, 1 ; Flags are affected.
add si, 1 ; Flags are affected.
cmp bh, 0 ; - Add this line
jne CmpString

I hope that this can be useful.