0

So I have a practice exam for assemblyx86 language

Write a void function, encryptStr(), that will encrypt a string. To encrypted the string, simply add one to each alphabetic (upper and lower case letters) character. All non-alphabetic characters (numbers, punctuation, spaces, etc.) are unchanged. Thus Hello Zoo 12 becomes Ifmmp [pp 12. The string is NULL terminated.

The function should return

  1. total count of all letters
  2. the count of ASCII digits ("0"-"9") and
  3. the total string length. The function is called as follows:
 encryptStr(inStr, &ltrCnt, &digitCnt, &strLen);

Where inStr is the input string ltrCnt, digitCnt, and strLen are the addresses of the unsigned double-word variables of where to return the appropriate values (note, passed variables not initialized to zero).

Your function must use the standard calling convention to access the arguments and save/restore only the appropriate registers used. You must define and show any additional data declarations that are used (if any). Points will be deducted for especially poor or inefficient solutions.

I tried to do it myself and wondering whether this is make sense....

       section  .data
        EXIT_SUCCESS        equ 0
        SYS_exit        equ 60
        NULL        equ     0
        SYS_write   equ 1
        STDOUT      equ 1
        input           db "11110", 0

    section .bss
        IntCnt      resd 1
        digitCnt    resd 1
        strLen      resd 1

    section .text
    global  _start
    _start:

        mov rdi, input
        mov rsi, IntCnt
        mov rdx, digitCnt
        mov rcx, strLen
        call encriptStr





        mov rdi, input
        call printString
        
    last:   
        mov rax, SYS_exit
        mov rdi, EXIT_SUCCESS
        syscall



    global encriptStr
    encriptStr:

        push    rbx
        push    r12
    ;------get addresses-----------------------

        mov rbx, rdi        ; addr nonaryStr
        mov r12, rsi        ; num
    ;------Set up--------------------------------
        mov     r11, 2          ; multiplier
        mov r10, 0          ; index
        mov r11, 0  
        mov qword [rSum], 0     ; set rSum to 0
        mov rax, 0          ; reset rax

    ;--------Multiplication Loop-------------------------
    multLoop:
        mov al, byte [rbx + r10]        ; get first char
        cmp al, NULL            ; if (char==NULL) DONE
        je  outLoop             ; else keep checking

        cmp al, "0"
        je  calculation
        cmp al, "1"
        je  calculation
        
        jmp outLoop


    calculation:
        sub al, 48              ; al - "0"
        movsx   r11, al
        mov qword [digit], r11      ;store digit into var
        mov rax, qword [rSum]       ;move rSum for Mult
        mul r11
        mov qword [rSum], rax       ; store result into rSum
        mov qword [rSum + 8], rdx
        
        add rax, qword [digit]      ; add digit to running sum
        mov qword [rSum], rax       ; store answer into running sum

        inc r10
        jmp multLoop

    ;----------Mult done----------------------------------------

         outLoop:
        mov rax, qword [rSum]       ; store running sum in rax
        mov qword [r12], rax        ; return limit to address of limit (qword)

         nonary2intDone:
            pop r12
        pop rbx
        ret
    ret
    ;********************************************************************
    ;  Generic function to display a string to the screen.
    ;  String must be NULL terminated.

    ;  Algorithm:
    ;   Count characters in string (excluding NULL)
    ;   Use syscall to output characters

    ; -----
    ;  HLL Call:
    ;   printString(stringAddr);

    ;  Arguments:
    ;   1) address, string
    ;  Returns:
    ;   nothing

    global  printString
    printString:

    ; -----
    ;  Count characters to write.

        mov rdx, 0
    strCountLoop:
        cmp byte [rdi+rdx], NULL
        je  strCountLoopDone
        inc rdx
        jmp strCountLoop
    strCountLoopDone:
        cmp rdx, 0
        je  printStringDone

    ; -----
    ;  Call OS to output string.

        mov rax, SYS_write          ; system code for write()
        mov rsi, rdi            ; address of char to write
        mov rdi, STDOUT         ; file descriptor for std in
                            ; rdx=count to write, set above
        syscall                 ; system call

    ; -----
    ;  String printed, return to calling routine.

    printStringDone:
        ret

    ; ******************************************************************
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • What is your `calculation` function doing? It's doing `rSum = rSum * digit + digit`, for AL=0 or 1. So it's a very complicated way to zero `rSum` or leave it unchanged, before adding the new `[digit]` (which you still have in R11, IDK why you store/reload there but not for mul). (And to zero RDX and use it to store a zero to the high 8 bytes of `rSum`). If this was supposed to be conversion of a base-2 ASCII string to an integer in a register... it's not doing that, and a 64x64 => 128-bit `mul` instruction doesn't particularly help you handle numbers wider than 64-bit. – Peter Cordes Jun 28 '22 at 09:14
  • Maybe you wanted `shl rdx, 1` / `or rdx, r11` inside the loop, and `mov [rSum], rdx` after, for converting base-2 strings to binary integers, i.e. packing the bits together. But this has no obvious connection to the encryption function your text talks about. – Peter Cordes Jun 28 '22 at 09:18
  • I assume the efficiency standards are fairly low for this beginner assignment, compared to how fast you could actually make it run on x86-64. That guarantees SSE2 is available, and counting matches in some ranges, plus incrementing bytes that are in that range, is something you can do for 16 bytes in parallel. (Or 32 with AVX2). See [How to count character occurrences using SIMD](//stackoverflow.com/a/54543009) for the counting part, and [Convert a String In C++ To Upper Case](//stackoverflow.com/a/37151084) for the alphabet-detection part. OR the alpha/digit masks together and `psubb` to inc – Peter Cordes Jun 28 '22 at 09:24
  • [How to access a char array and change lower case letters to upper case, and vice versa](https://stackoverflow.com/a/35936844) is a better Q&A for detecting alphabetic characters (upper and lower), including vectorized. – Peter Cordes Jun 28 '22 at 09:40
  • 1
    TL:DR: no, your attempt doesn't make any sense. It doesn't appear to be even trying to implement the thing your assignment says to implement. (I just noticed that you earlier `mov r11, 2` as a multiplier, so I guess the `movsx r11, al` overwriting it was unintended. If you fixed that, it might possibly be correct base 2 ASCII -> integer, but it wouldn't make sense in terms of efficiency. I'd call that "especially inefficient".) – Peter Cordes Jun 28 '22 at 10:02

0 Answers0