Hello!  :D
I've just began to learn asm, and I'd like to write some simple string functions.
I actually came up with the whole idea/algorithm only I'm one step away from making it work.
Basically I have a string (char array actually) declared as
stringzor db "test",0

and then I want to copy its address to dx, so I do this:
mov dx,stringzor
.
Next I want to compare dx with 0 (to check if it's the end of the string), thus in a loop I do a:
cmp ,0

and if it's not equal, I jump and increment cx (which is my string lenght counter) and dx so in the next loop cycle I'll be checking another character. The problem is that it doesn't work as it should, because it counts a lot more characters then in the string. I'd like to ask you for some help, and even better, if someone could write a simple example. If there's something wrong, just ask me and I'll add more information.
Posted on 2007-03-01 10:20:41 by zdebel
you seem to be using 16-bit code, in which you cannot use "dx" for address  (eg. ""). If it's 32bit code, then using DX is error too.

also, which assembler are you using?
Posted on 2007-03-01 11:18:59 by vid
thank you for your reply, I'm using nasm, and for the moment I'm booting from a floppy in qemu, I just want to code at the lowest level possible for now, so, I can't use 16 bit registers for addresses (and yes, I'm doing 16bit coding for now), and so, how should I do it properly ?
Posted on 2007-03-01 11:24:40 by zdebel
most simple procedure to count length of string:

;args: SI = string
;ret: CX=length
;destroys CX and SI
strlen:
xor cx, cx
.next:
inc cx
lodsb
cmp al, 0
jne lodsb
dec cx ;don't count ending zero
ret


"lodsb" is equivalent for "mov al," and "inc si".
Posted on 2007-03-01 11:39:08 by vid
I just came up with something similiar, the problem was I was using the mbr of a floppy to boot it, and I just spotted that because I used 'section .data' the variable was put after the 512th byte so it wouldn't work, anyway, thank you very much for your help, and this topic can be closed ^^
Posted on 2007-03-01 11:44:30 by zdebel
NASM doesn't relocate the data section if you use AFAIK. The boot sector of my kernel has data but I have not defined them using . I have simply put them at the bottom of the code.
Posted on 2007-03-01 13:19:08 by XCHG
ok... so I'm doing it in DOS now, to make things easier ^^, but I can't make this work... so I'll post my code and maybe someone will be so generous to point out what I'm doing wrong.
string.asm:
putchar: ;the ascii key code needs to be put in AL register
mov ah,0Eh
int 10h
ret
strlen: ;stores the count in cx, the string ADDRESS is in si
xor cx,cx
mov al,
cmp al,0
jne strlen1
ret ;if empty. simply return
strlen1:
inc cx
call putchar;print the current char to see if it works
inc si
mov al,
cmp al,0
jne strlen1
ret ;if the end of the string, return ;-)

string_test.asm (the main file, I compile it with `nasm -o string.exe string_test.asm):
section .text
mov al,"z" ;just a starting "check point"
call putchar
mov si,lolzor
call strlen
mov al,"b" ;just an ending"check point"
call putchar
ret
%include "string.asm"
section .data
lolzor db "testZOR",0


The output should look like this: "ztestZORb" but it's just some garbage, which begins with z and end with b, but the string isn't printed :(
Posted on 2007-03-02 12:34:36 by zdebel

%DEFINE PTR

; ---------------------------------
  MOV    AL , 'z'
  CALL    __PrintChar
  MOV    SI , String1
  CALL    __PrintString
  MOV    AL , 'b'
  CALL    __PrintChar
  HLT
; ---------------------------------
__PrintString:
  ; -> SI = String's offset
  CALL    __StrLen
  TEST    AX , AX
  JE      @@__PrintStringEP
  MOV    CX , AX
  @@__PrintStringLoop:
    MOV    AL , BYTE PTR
    CALL    __PrintChar
    INC    SI
    DEC    CX
    JNE    @@__PrintStringLoop
  @@__PrintStringEP:
    RET
; ---------------------------------
__PrintChar:
  ; -> AL = Input character
  MOV    AH , 0x0E
  INT    0x10
  RET
; ---------------------------------
__StrLen:
  ; -> SI = String's offset
  ; <- AX = Length of the string
  PUSH    SI
  XOR    AX , AX
  @@__StrLenLoop:
    MOV    DL , BYTE PTR
    TEST    DL , DL
    JE      @@__StrLenEP
    INC    AX
    INC    SI
    JMP    @@__StrLenLoop
  @@__StrLenEP:
    POP    SI
    RET
; ---------------------------------

  String1    DB      'TestZOR', 0x00


I hate to code like this but if you are more comfortable this way, ...

If I was coding the program, I would simple eliminate the __StrLength procedure and simply build it in the __PrintString procedure like the below code. I would also avoid using __PrintChar in __PrintString and make __PrintString print the characters without using the former procedure:


%DEFINE PTR

; ---------------------------------
  MOV    AL , 'z'
  CALL    __PrintChar
  MOV    SI , String1
  CALL    __PrintString
  MOV    AL , 'b'
  CALL    __PrintChar
  HLT
; ---------------------------------
__PrintString:
  ; -> SI = String's offset
  MOV    AH , 0x0E
  .PrintStringLoop:
    MOV    AL , BYTE PTR
    TEST    AL , AL
    JE      .PrintStringEP
    INT    0x10
    INC    SI
    JMP    .PrintStringLoop
  .PrintStringEP:
    RET
; ---------------------------------
__PrintChar:
  ; -> AL = Input character
  MOV    AH , 0x0E
  INT    0x10
  RET
; ---------------------------------

  String1    DB      'TestZOR', 0x00


Posted on 2007-03-02 13:02:35 by XCHG
XCHG, Thank You very much for this, it really helped me a lot ^^ I got it working and I'm off to writting some more asm code :D
Posted on 2007-03-02 14:08:41 by zdebel