Author Topic: Rotate 64-bit word  (Read 62199 times)

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Rotate 64-bit word
« Reply #30 on: June 12, 2021, 01:46:45 PM »
Shouldn't

  shld  eax, edx, 8
  shld  edx, ecx, 8

actually be

  shld  eax, edx, 8
  shr   edx,8
  shld  edx, ecx, 8

?

It seems to me that after the first shld, the low byte of edx is all zero. So you are inserting a zero byte into your result.
The lower byte of EAX will be filled with the upper byte of EDX in the first SHLD. SHLD.

A small program to demonstrate:

Code: [Select]
  ; Using x86-64 because I don't have a i386 linux here.
  bits  64
  default rel

  section .rodata

hexdigits:
  db  "0123456789ABCDEF"
nl:
  db  `\n`

  section .text

  global _start
_start:

  mov  edx,0x01234567
  mov  eax,0x89abcdef

  push rax
  push rdx
  mov   eax,edx
  call  printhex
  mov   eax,[rsp+8]
  call  printhex

  call  printnl

  pop  rdx
  pop  rax

  call f

  push rax
  mov  eax,edx
  call printhex
  pop  rax
  call printhex

  call printnl

  mov  eax,60
  xor  edi,edi
  syscall

; Under test...
f:
  mov   ecx,eax
  shld  eax,edx,8     ; EAX << EDX << 8
  shld  edx,ecx,8     ; EDX << ECX << 8
  ret

printnl:
  mov  eax,1
  mov  edi,eax
  mov  edx,eax
  lea  rsi,[nl]
  syscall
  ret

printhex:
  mov  ebx,8

  rol  eax,4
.loop:
  push rax

  and  eax,0xf
  lea  rsi,[hexdigits+eax] 
  mov  eax,1
  mov  edi,eax
  mov  edx,eax
  syscall

  pop   rax

  rol   eax,4
  dec   ebx
  jnz   .loop

  ret

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #31 on: June 12, 2021, 02:24:34 PM »
As I understand it (asterisk representing zero):

The 1st shld changes eax (" ABC") to "ABCD" leaving edx with "EFG*".

The 2nd shld changes edx ("EFG*") to "EFG " leaving ecx with "ABC*".

That is, if ecx holds a copy of eax's initial value (" ABC").

-mjrice

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Rotate 64-bit word
« Reply #32 on: June 12, 2021, 06:10:45 PM »
As I understand it (asterisk representing zero):

The 1st shld changes eax (" ABC") to "ABCD" leaving edx with "EFG*".

The 2nd shld changes edx ("EFG*") to "EFG " leaving ecx with "ABC*".

That is, if ecx holds a copy of eax's initial value (" ABC").

-mjrice
Nope... as demonstrated by the code above, your "string" in EDX:EAX as 0x20414243:0x44454647, the first SHLD will get EAX as 0x45464720, and the second EDX as 0x41424344. So your "string" will be translated from " ABCDEFG" to "ABCDEFG ".

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #33 on: June 12, 2021, 07:39:19 PM »
" ABCDEFG" to "ABCDEFG " happens to be exactly what it is supposed to do, move all the leading blanks, one by one, from left to right. That's why I needed to know how many leading blanks are in the qword. I thought I made that very clear.

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #34 on: June 12, 2021, 08:16:11 PM »
The input to rot8left64, no exceptions (X=blank), A...H  represent alphanumeric characters.
"ABCDEFGH"
"XABCDEFG"
"XXABCDEF"
"XXXABCDE"
"XXXXABCD"
"XXXXXABC"
"XXXXXXAB"
"XXXXXXXA"






Offline debs3759

  • Global Moderator
  • Full Member
  • *****
  • Posts: 224
  • Country: gb
    • GPUZoo
Re: Rotate 64-bit word
« Reply #35 on: June 12, 2021, 08:29:07 PM »
I stand corrected. I have never used shld, so just looked it up. Didn't realise that shld eax,edx,8 only changes eax.
My graphics card database: www.gpuzoo.com

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Rotate 64-bit word
« Reply #36 on: June 13, 2021, 01:22:53 AM »
The input to rot8left64, no exceptions (X=blank), A...H  represent alphanumeric characters.
"ABCDEFGH"
"XABCDEFG"
"XXABCDEF"
"XXXABCDE"
"XXXXABCD"
"XXXXXABC"
"XXXXXXAB"
"XXXXXXXA"
That's because there is something wrong with the calling convention you are using... AND I made a mistake... rotating the string to left as an uint64 is the same as rotating the chars to the right:
Code: [Select]
;  rot.asm
  bits  64
  default rel

  section .text

  global rot
rot:
  mov   eax,[rdi]
  mov   edx,[rdi+4]

  mov   ecx,eax
  shld  eax,edx,8
  shld  edx,ecx,8

  mov   [rdi],eax
  mov   [rdi+4],edx
  ret
Code: [Select]
/* test.c */
#include <stdio.h>

extern void rot( char * );

int main( void )
{
  char s[] = " ABCDEFG";

  printf( "%s\n", s );
  rot( s );
  printf( "%s\n", s );
}
Code: [Select]
$ nasm -felf64 -o rot.o rot.asm
$ cc -O2 -c -o test.o test.c
$ cc -o test test.o
$ ./test
 ABCDEFG
G ABCDEF
To rotate the chars to the left I should rotate to the right:
Code: [Select]
rot8left64_:
  mov  ecx,edx
  shrd  edx,eax,8
  shrd  eax,ecx,8
  ret

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #37 on: June 13, 2021, 03:49:50 AM »
I'm trying to duplicate the code, and its execution, in my post from June 08, 2021, 10:29:54 PM, the one that gave G ABCDEFG. In that I compiled krot8left64.asm, eliminating the need for INHALT, so I must have changed your rot8left64.asm to krot8left64.asm, and its call from fortran to krot8left64, as below. But now the link step fails and I'm failing to see why. Your code is as it was in that post, except for the addition of the "K".  Do
you see a problem?

;;;;;;;;;;;;;;;;;;;;; 

  100 FORMAT(A8)
      READ(*,100) LW
      WRITE(*,100) LW
      MW=KROT8LEFT64(LW)
      WRITE(*,100) MW
      END

;;;;;;;;;;;;;;;;;;;;;

  bits 32      ; to be sure.

struc krot8left64_stk
      resd 1
.ptr: resd 1
endstruc

  global krot8left64_
rot8left64_:
  mov   eax,[esp+krot8left64_stk.ptr]  ; get pointer

  mov   edx, [eax+4]   ; get QWORD from pointer.
  mov   eax, [eax]

  mov   ecx,edx
  shld  edx,eax,8
  shld  eax,ecx,8
  ret

;;;;;;;;;;;;;;;;;;;;;
mrice@debian10-uni:~$ nasm -f elf krot8left64.asm
mrice@debian10-uni:~$ gfortran -c -fdefault-integer-8 -fdefault-real-8 -fno-range-check test.f95 -o test.o
mrice@debian10-uni:~$ gfortran test.o krot8left64.o -o test
/usr/bin/ld: test.o: in function `MAIN__':
test.f95:(.text+0x115): undefined reference to `krot8left64_'
collect2: error: ld returned 1 exit status
mrice@debian10-uni:~$

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #38 on: June 13, 2021, 01:33:49 PM »
I was missing to "K" on one of the rot8left64's. Fixed.

mrice@debian10-uni:~$ nasm -f elf krot8left64.asm
mrice@debian10-uni:~$ gfortran -c -fdefault-integer-8 -fdefault-real-8 -fno-range-check test.f95 -o test.o
mrice@debian10-uni:~$ gfortran test.o krot8left64.o -o test
mrice@debian10-uni:~$ ./test
 ABCDEFG
 ABCDEFG
ABCDEFG
mrice@debian10-uni:~$

The fortran:

  100 FORMAT(A8)
      READ(*,100) LW
      WRITE(*,100) LW
      MW=KROT8LEFT64(LW)
      WRITE(*,100) MW
      END
     
The asm:

  bits 32      ; to be sure.

struc krot8left64_stk
      resd 1
.ptr: resd 1
endstruc

  global krot8left64_
krot8left64_:
  mov   eax,[esp+krot8left64_stk.ptr]  ; get pointer

  mov   edx, [eax+4]   ; get QWORD from pointer.
  mov   eax, [eax]

  mov   ecx,edx
  shrd  edx,eax,8
  shrd  eax,ecx,8
  ret

Thanks to all.

-mjrice

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #39 on: June 13, 2021, 04:36:31 PM »
Just after posting my previous message my Debian x86 Box went kaput on me, Will get it all back later today as I have backup on Dropbox. By the way, I'm doing this for fun. Have been at it since the late '70s when I implemented part of Weizenbaum's SLIP on a 16 bit IBM 1130 clone, later doing it again for 64-bit.  It's quite a surprising "app" for the early 1960s. Would be happy to share what I have with anyone interested. Will post an example when I get operational again.

The shifting (rotation?) function krot8left64.asm needs to pass its input qword to yet another function, one that returns the qword's number of blanks, it to be used to loop through the shrds the needed number of times. Or maybe there's a simpler way to do this without a function call?

-mjrice

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #40 on: June 14, 2021, 02:45:06 PM »
I modified the bottom part of my code, as below, but something is amiss. My input is "XXXXXXXA" (X as blank) but only get a blank output. Why didn't the "A" get shifted left 6 times?

  mov   esi, 6
l2:
  shrd  edx,eax,8
  shrd  eax,ecx,8
  dec esi
  jnz l2
  ret

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #41 on: June 14, 2021, 03:37:16 PM »
Just realized I wasn't resaving edx  in ecx after a shift.

mrice@debian10-uni:~/work$ ./test
       A
       A
 A     
mrice@debian10-uni:~/work$

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #42 on: June 16, 2021, 12:55:15 AM »
An attempt at counting blanks. Anyone see a problem in my code? Answer should be 3.

-mjrice

mrice@debian10-uni:~/work$ ./test
   ABCDE
   ABCDE

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0xb7cfa74b
#1  0xb7cf984e
#2  0xb7f4ad6b
#3  0x4e2045
Segmentation fault
mrice@debian10-uni:~/work$

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  bits 32      ; to be sure.

Section .data
indx   dw 0
nblank   dw 0

struc kblank_stk
      resd 1
.ptr: resd 1
endstruc

  global kblank_
kblank_:
  mov   eax,[esp+kblank_stk.ptr]  ; get pointer

  mov   edx, [eax+4]   ; get QWORD from pointer.
  mov   eax, [eax]

testeax:
  cmp   byte [eax+indx], " "
  jnz   testedx
  inc   dword [nblank]
testedx:
  cmp   byte [edx+indx], " "
  jnz   bumpup
  inc   dword [nblank]
bumpup:
  inc   dword [indx]
  cmp   dword [indx], 4
  jz   finished
  jmp   testeax
finished:
  mov   eax, nblank
  mov   edx, 0
  ret 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  100 FORMAT(A8)
  110 FORMAT(I8)
      READ(*,100) LW
      WRITE(*,100) LW
      MW=KBLANK(LW)
      WRITE(*,110) MW
      END



Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #43 on: June 18, 2021, 02:03:40 AM »
How does one test a single byte of a register for a particular value? Maybe one doesn't, or can't?

-mjrice

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #44 on: June 18, 2021, 01:39:47 PM »
;;;;;This

  mov   edx, [eax+4]   ; get QWORD from pointer.
  mov   eax, [eax]

  mov   ecx, 0

  cmp   al, 32
  jnz   finished
  inc   ecx
finished:
  mov   eax, ecx
  mov   edx, 0
  ret

;;;;;Produced

mrice@debian10-uni:~/work$ ./test
ABCDEFG
ABCDEFG
       0
mrice@debian10-uni:~/work$

;;;;;Question

For an input of "ABCDEFG ", doesn't register AL hold the blank?

-mjrice