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

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Rotate 64-bit word
« Reply #45 on: June 20, 2021, 09:49:35 AM »
How do you get the size of an string? I recall that FORTRAN don't use NUL char terminated strings...

Hummmm... reading about FORTRAN seems like it not allow for variable size strings (am I right?). So, to scan for a string of 8 chars counting spaces, you should do something like this.

Code: [Select]
  bits  32

  section .text

struc kblank_stk
      resd  1   ; ret addr
.str: resd  1   ; pointer to string.
endstruc

  global kblank_

kblank_:
  ; SysV ABI for i386 mode. Must preserve ESI.
  push  esi

  mov   ecx,8       ; # of chars to check.
  xor   edx,edx     ; # of spaces found.

  ; Get string pointer from stack.
  mov   esi,[esp+kblank_stk.str]

  jmp   .test
 
  align 4
.loop:
  lodsb             ; AL = next char from string.
  cmp   al,' '      ; AL == ' '?
  jnz   .skip       ; No, skip counting
  inc   edx         ; Increment # spaces found
.skip:
  dec   ecx         ; Decrement char counter
.test:
  test  ecx,ecx     ; Is there any char left?
  jnz   .loop       ; Yes, loop.

  ; Restore ESI.
  pop   esi

  mov   eax,edx     ; return count in EAX.

  ret
« Last Edit: June 20, 2021, 10:13:44 AM by fredericopissarra »

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #46 on: June 21, 2021, 01:55:55 AM »
Welcome back. I think you're correct about the strings.

I've been busy. After my last message I poked around some and finally wrote some code that will count blanks in my 8 character 64-bit variables. I'm using ECX as a counter (code below). Tried using ESI so I wouldn't have to set it for the later shifting but got segmentation errors. Compiler, don't know which, perhaps both, seem to flake out on me, was giving me segmentation errors for the code below earlier, so I removed both NASM and gfortran and reinstalled both, after rebooting. The code then ran fine. Weird, huh?  I'll try ESI again tomorrow. I knew the code was good because when I finally got it to run I emailed a copy to myself. I'm aware that EAX must be restored before
shifting occurs. Will try out your code tomorrow.

-mjrice


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

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

  bits 32      ; to be sure.

struc kjunk_stk
      resd 1
.ptr: resd 1
endstruc

  global kjunk_
kjunk_:
  mov   eax,[esp+kjunk_stk.ptr]  ; get pointer

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

  mov ecx, 0

l1:
  cmp al, 32
  jnz l2
  inc ecx
l2:
  ror eax, 8
  cmp al, 32
  jnz l3
  inc ecx
l3:
  ror eax, 8
  cmp al, 32
  jnz l4
  inc ecx
l4:
  ror eax, 8
  cmp al, 32
  jnz l5
  inc ecx
l5:
;  ror eax, 8
  mov eax, edx

l6:
  cmp al, 32
  jnz l7
  inc ecx
l7:
  ror eax, 8
  cmp al, 32
  jnz l8
  inc ecx
l8:
  ror eax, 8
  cmp al, 32
  jnz l9
  inc ecx
l9:
  ror eax, 8
  cmp al, 32
  jnz finished
  inc ecx

finished:
  mov eax, ecx
  mov edx, 0
ret




Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #47 on: June 21, 2021, 02:02:27 PM »
Code I sent worked fine after changing ECX to ESI.

Added this line up before the rotations to save EAX

;  mov   ebx, eax   ;save EAX

It alone caused a seg-fault. I commented it out and, suprise! - it worked again.

Also, after label "finished:", I swapped these

  mov   eax, esi
  mov   edx, 0

for

;  mov   eax, ebx   ;restore EAX
;
;  mov   ecx, edx
;
;l10:
;  shrd  edx,eax,8
;  shrd  eax,ecx,8
;  mov   ecx, edx
;  dec esi
;  jnz l10

Can you think of any reason why using EBX would cause a seg-fault?

 

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #48 on: June 21, 2021, 06:27:04 PM »
Just ran the code you supplied:

ABCD   
ABCD   
       0
mrice@debian10-uni:~/work$ ./test
ABCDEF 
ABCDEF 
       0
mrice@debiIan10-uni:~/work$ ./test
A       
A       
       0

Let me know if you have any changes.


Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #49 on: June 21, 2021, 07:21:18 PM »
Got my code working.  EAX gets used and abused in the blank search, so I pushed it before, and popped it after. Will post code later. May be a way to make it briefer now that we have it working.

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

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #50 on: June 22, 2021, 01:31:13 AM »

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

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

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


The function, named lanorm.asm, because that's what it's called by the other code.

 bits 32      ; to be sure.

struc lanorm_stk
      resd 1
.ptr: resd 1
endstruc

  global lanorm_
lanorm_:
  mov   eax,[esp+lanorm_stk.ptr]  ; get pointer

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

  push   eax      ;save eax
  mov esi, 0      ;initialize counter for blanks

l1:
  cmp al, 32      ;search EAX for blanks
  jnz l2
  inc esi
l2:
  ror eax, 8
  cmp al, 32
  jnz l3
  inc esi
l3:
  ror eax, 8
  cmp al, 32
  jnz l4
  inc esi
l4:
  ror eax, 8
  cmp al, 32
  jnz l5
  inc esi
l5:
  mov eax, edx      ;search EDX for blanks
l6:
  cmp al, 32
  jnz l7
  inc esi
l7:
  ror eax, 8
  cmp al, 32
  jnz l8
  inc esi
l8:
  ror eax, 8
  cmp al, 32
  jnz l9
  inc esi
l9:
  ror eax, 8
  cmp al, 32
  jnz finished
  inc esi
finished:
  pop   eax      ;restore EAX
  mov   ecx, edx
l10:
  shrd  edx,eax,8
  shrd  eax,ecx,8
  mov   ecx, edx
  dec esi
  jnz l10
  ret   

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #51 on: June 22, 2021, 03:20:19 PM »
Finding that the AL register points at the "highest" character :

mov    al, 63

ABCDEFGH becomes ?BCDEFGH

Here's a much shorter version, with no blank counting.

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

bits 32      ; to be sure.

struc lanorm_stk
      resd 1
.ptr: resd 1
endstruc

  global lanorm_
lanorm_:
  mov   eax,[esp+lanorm_stk.ptr]  ; get pointer

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

  mov   ecx,edx

loop:
  cmp   al, 32
  jnz   finished
   shrd  edx,eax,8
   shrd  eax,ecx,8
  mov   ecx, edx
  jmp   loop
finished:
  ret

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Rotate 64-bit word
« Reply #52 on: June 23, 2021, 01:18:32 PM »
You still don't provide any reference of what calling convention is used by gfortran and what exactly you want to do, so the only thing I can do is to GUESS...

gfortran (and fortran, in general) is a shitty compiler in terms of optimization. You **could** make your function in fortran and take e look at the generated assembly code using -S option (and `-masm=intel` to see assembly in intel syntax, not AT&T syntax), but gfortran creates a bad code (in terms of optimization)...

OR.. you can use `gcc` (which is a very good compiler, in terms of optimization)... Here's a test of a function rotating 8 first chars in a string:
Code: [Select]
/* test.c */
#include <stdio.h>
#include <stdint.h>
#include <limits.h>

// Generic rotate left 1 QWORD 'bits' bits.
static uint64_t rotateleft ( uint64_t n, unsigned int bits )
{
  // Rotate bits to the left.
  n = ( n << bits ) |
      ( n >> sizeof ( uint64_t ) * CHAR_BIT - bits );

  return n;
}

// This will deal only with the 8 first chars.
// Rotating them 1 char to the right.
void krotateright ( char *s )
{
  // Convert the first 8 bytes to QWORD.
  uint64_t n = * ( uint64_t * ) s;

  // Rotate CHAT_BIT bits and stores back at the memory pointed by s.
  * ( uint64_t * ) s = rotateleft ( n, CHAR_BIT );
}

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

  for ( int i = 0; i < 8; i++ )
  {
    printf ( "\"%s\" --rotate right 1 char--> ", s );
    krotateright ( s );
    printf ( "\"%s\"\n", s );
  }
}
Compiling and running:
Code: [Select]
$ cc -O2 -o test test.c
$ ./test
"ABCDEFG " --rotate right 1 char--> " ABCDEFG"
" ABCDEFG" --rotate right 1 char--> "G ABCDEF"
"G ABCDEF" --rotate right 1 char--> "FG ABCDE"
"FG ABCDE" --rotate right 1 char--> "EFG ABCD"
"EFG ABCD" --rotate right 1 char--> "DEFG ABC"
"DEFG ABC" --rotate right 1 char--> "CDEFG AB"
"CDEFG AB" --rotate right 1 char--> "BCDEFG A"
"BCDEFG A" --rotate right 1 char--> "ABCDEFG "
If you compile with:
Code: [Select]
$ cc -O2 -S -masm=intel -fcf-protection=none test.c -o test.sThis will generate the assembly listing of the entire code. Take a look at `test.s` and you'll see something like this:
Code: [Select]
krotateright:
  push  ebx
  mov   ecx, [esp+8]
  mov   eax, [ecx]
  mov   edx, [ecx+4]
  mov   ebx, eax
  shrd  eax, edx, 8
  shrd  edx, ebx, 8
  mov   [ecx], eax
  mov   [ecx+4], edx
  pop   ebx
  ret
Which isn't the best code possible, but it is a start.
« Last Edit: June 23, 2021, 01:24:35 PM by fredericopissarra »

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #53 on: June 24, 2021, 12:56:28 AM »
A lot of this is already implemented. Will send an example to give you a better idea of what SLIP all about.

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #54 on: June 24, 2021, 01:26:24 PM »
Two figures attached, both from the ACM document "Symmetric List Processor," author Joseph Weizenbaum.

The part I'm working on now allows a user to enter a textual representation of a list, like the one in Fig. 3, from the keyboard, and construct from it an internal list, as shown in the diagrams. Currently lists can only be constructed programmatically.  Will post an example of that next.

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #55 on: June 24, 2021, 02:37:30 PM »
Ran this this morning.

! Sums structural list of real numbers, prints list and sum.
      dimension space(100)    !  Set aside list space
      call initas(space,100)

      l1 = 0
      l2 = 0
      idummy = list(l1)    !  Function list both assigns list-name to its argument and returns the list name
      idummy = list(l2)

      idummy = newbot(1.0,l1)
      idummy = newbot(6.0,l2)
      idummy = newbot(l2,l1)
      idummy = newbot(3.0,l1)
      call prlsts(l1,3)    !  3 means list is real numbers; 2 is characters; 1 is integers
      total = 0.0
      k = lrdrov(l1)       !  Create list reader
    1 x = advsel(k,f)    !  Advance reader structurally, (s), by element (e). Parameter f is a flag
    if (f .ne. 0) go to 2  !  Reader at end of list?
      total = total + x
      go to 1
    2 continue
      print *, total
      end

mrice@debian10-uni:~/slip/test$ ./test
                    BEGIN LIST
                         1.0000
                     BEGIN SUBLIST
                         6.0000
                     END SUBLIST
                         3.0000
                    END LIST
   10.000000000000000 

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #56 on: June 24, 2021, 02:51:49 PM »
Btw, used your shifting function to create 8 masks I'll need for my next task. Just changed the  Rs to Ls in the shifting functions. Started at the low end with 255 rather than the high end with -72 quadrillion.

mrice@debian10-uni:~$ ./test
FF00000000000000
  FF000000000000
    FF0000000000
      FF00000000
        FF000000
          FF0000
            FF00
              FF

! Create a mask for each of 8 characters
      INTEGER CP,COPY
      DIMENSION CP(8)
  100 FORMAT(Z16)

      DO 10, I=1,8
      CP(I)=0
   10 CONTINUE

! Start with the low end
      CP(8)=255

! Shift the other 7 leftward from it
      DO 20, I=7,1,-1
      COPY=CP(I+1)
      CP(I)=KROT8LEFT64(COPY)
   20 CONTINUE

      DO 30, I=1,8
      WRITE(*,100) CP(I)
   30 CONTINUE

      END

Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #57 on: June 25, 2021, 04:15:32 PM »
Oops, asked for the G CP(7), shifted it rightward, got the B instead.

      READ(*,100) IGET
      IWORD=ISHFT(IAND(IGET,CP(7)),-8)

mrice@debian10-uni:~$ ./test
ABCDEFGH
B
mrice@debian10-uni:~$

Think of the variable IGET as one 64 bit  word  from an array of 10 of them read from a punched card.  The characters on the word are removed from that word one at a time and shoved one at a time into a waiting all blank 64 bit word from the left end, the same for each succeeding character, shifting earlier characters leftward, until a blank or a comma is found, then the word shifted leftward until all blanks, if any, are to the right of the other characters, forming a token which can be pushed up from the bottom of a waiting list. Encountering a right paren character completes the list. The function RDLSTA recursively reads sublists encountered in this process.

Looking for a way to data-ize the masks to be local to the function. Will try this later:

!      DATA CP(1:8)
!       /
!        Z'FF00000000000000',
!        Z'00FF000000000000',
!        Z'0000FF0000000000',
!        Z'000000FF00000000',
!        Z'00000000FF000000',
!        Z'0000000000FF0000',
!        Z'000000000000FF00',
!        Z'00000000000000FF'
!       /




Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #58 on: June 26, 2021, 01:53:55 AM »
root@debian10-uni:/home/mrice# ./test
              FF
            FF00
          FF0000
        FF000000
      FF00000000
    FF0000000000
  FF000000000000
FF00000000000000
root@debian10-uni:/home/mrice# gfortran -c -fdefault-integer-8 -fdefault-real-8 -fno-range-check test.f95 -o test.o
root@debian10-uni:/home/mrice# gfortran test.o krot8left64.o -o test
root@debian10-uni:/home/mrice# ./test
ABCDEFGH
G

Reversed the order of  the masks and got the 7th character, the G. The computer that was used in he early 1960s must have been big endian?

Can't find a gfortran that will accept hexadecimals in a data statement. Tried gfortran-8. Now to write SQOUT, a function that will "squeeze out" individual characters as this fortran code does.  Another function, to come later, called SQIN will squeeze the output from SQOUT into a waiting, initially all blank, 64 bit word a character at a time.

A line from the fortran code of the SLIP document:

SYMBOL = SQIN(CP(8),SQOUT(CP(IC),CRDBUF(IW)),PLACE)

CP(8) should probably be changed to CP(1)? Also, since IC currently starts at 1 and increments upward, it should begin at 8 and decrement downward.  Or, easier, re-reverse the order of the masks? :-)



Offline mjrice

  • Jr. Member
  • *
  • Posts: 66
Re: Rotate 64-bit word
« Reply #59 on: June 27, 2021, 03:20:28 PM »
Finally found a way to localize the masking variables to the RDLSTA function.. Using them to print a few characters on the low end of "ABCDEFGH". On to asm function SQOUT(MASK,WORD).

mrice@debian10-uni:~$ ./test
ABCDEFGH
H
G
F
E
mrice@debian10-uni:~$


! Create a mask for each of 8 characters
      INTEGER CP(8),COPY
      DATA CP(1)/Z'00000000000000FF'/
      DATA CP(2)/Z'000000000000FF00'/
      DATA CP(3)/Z'0000000000FF0000'/
      DATA CP(4)/Z'00000000FF000000'/
      DATA CP(5)/Z'000000FF00000000'/
      DATA CP(6)/Z'0000FF0000000000'/
      DATA CP(7)/Z'00FF000000000000'/
      DATA CP(8)/Z'FF00000000000000'/

  100 FORMAT(A8)
  110 FORMAT(Z16)
 
!      DO 30, I=1,8
!      WRITE(*,110) CP(I)
!   30 CONTINUE

      READ(*,100) IGET

      IWORD=ISHFT(IAND(IGET,CP(8)),0)
      WRITE(*,100) IWORD
      IWORD=ISHFT(IAND(IGET,CP(7)),-8)
      WRITE(*,100) IWORD
      IWORD=ISHFT(IAND(IGET,CP(6)),-16)
      WRITE(*,100) IWORD
      IWORD=ISHFT(IAND(IGET,CP(5)),-24)
      WRITE(*,100) IWORD

      END