title: Assembly Program to handle Escape Characters
body: <p>edit 10/2/16 - it's no longer segfaulting but the lowercase characters are not converting - here's what I changed in the lowercase label:</p>
  
  <pre><code>lowercase:
          cmp     ax, 'a'                  ; is it a?
          jb      slashprint               ; jump out if it's below a
          cmp     ax, 'z'                  ; is it z?
          ja      slashprint               ; jump out if it's above z
          mov     eax, [esi]               ; move the char to eax to index
          mov     ebx, mappings            ; point to the mappings array
          sub     eax, 97                  ; convert the lower case letter to decimal
          mov     ax, [ebx + eax]          ; indexed addressing done here
          jmp     done  
  </code></pre>
  
  <p>I'm working on a program that will allow me to take a string from a user, detect escape sequences and properly output the converted message. I know already that I need to clean up some of the logic inside the subroutine handle_ESC but I'm attempting to test and debug one situation at a time. My issue is that every time I return from the subroutine and go to add the character I modified to the new string stored in edi (on the first line of label L1_cont), I get a segfault. So far I've just been focused on getting it to accept the lower case escape sequences. edit: changed a few things around. Now I'm not segfaulting when typing 2 slashes, but it also doesn't do what I want it to do. It doesn't print anything. Still segfaulting when looking at a lowercase letter from the same line. With the changes I made it should never reach that instruction.</p>
  
  <pre><code>%define STDIN 0
  %define STDOUT 1
  %define SYSCALL_EXIT  1
  %define SYSCALL_READ  3
  %define SYSCALL_WRITE 4
  %define BUFLEN 256
  
  
          SECTION .data                   ; initialized data section
  
  msg1:   db "Enter string: "             ; user prompt
  len1:   equ $-msg1                      ; length of first message
  
  msg2:   db "Original: "                 ; original string label
  len2:   equ $-msg2                      ; length of second message
  
  msg3:   db "Convert:  "                 ; converted string label
  len3:   equ $-msg3
  
  msg4:   db 10, "Read error", 10         ; error message
  len4:   equ $-msg4
  
  msg5:   db 10, "Error: unknown escape sequence", 10 ; unknown escape error (not sure this works)
  len5:   equ $-msg5
  
  msg6:   db 10, "Error: octal value overflow!", 10 ; overflow error
  len6:   equ $-msg6
  
  ; Declare the array using mappings.
  mappings: db 7, 8, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, 13, -1, 9, -1, 11, -1, -1, -1, -1
  
  
          SECTION .bss                    ; uninitialized data section
  buf:    resb BUFLEN                     ; buffer for read
  newstr: resb BUFLEN                     ; converted string
  rlen:   resb 4                          ; length
  
  
          SECTION .text                   ; Code section.
          global  _start                  ; let loader see entry point
  
  _start: nop                             ; Entry point.
  start:                                  ; address for gdb
  
          ; prompt user for input
          ;
          mov     eax, SYSCALL_WRITE      ; write function
          mov     ebx, STDOUT             ; Arg1: file descriptor
          mov     ecx, msg1               ; Arg2: addr of message
          mov     edx, len1               ; Arg3: length of message
          int     080h                    ; ask kernel to write
  
          ; read user input
          ;
          mov     eax, SYSCALL_READ       ; read function
          mov     ebx, STDIN              ; Arg 1: file descriptor
          mov     ecx, buf                ; Arg 2: address of buffer
          mov     edx, BUFLEN             ; Arg 3: buffer length
          mov     [ecx + edx], byte 0     ; null terminate the read buffer
          sub     edx, 1                  ; make sure the buffer length is 1 less than BUFLEN
          int     080h
  
          ; error check
          ;
          mov     [rlen], eax             ; save length of string read
          cmp     eax, 0                  ; check if any chars read
          jg      read_OK                 ; &gt;0 chars read = OK
          mov     eax, SYSCALL_WRITE      ; ow print error mesg
          mov     ebx, STDOUT
          mov     ecx, msg4
          mov     edx, len4
          int     080h
          jmp     exit                    ; skip over rest
  read_OK:
  
  
          ; Loop for iterating over string
  
  L1_init:
          mov     esi, buf                ; point to start of buffer
          mov     edi, newstr             ; point to start of new string
          mov     bx, [mappings]          ; point to the mappings array
  
  L1_top:
          mov     al, [esi]               ; get a character
          inc     esi                     ; point to the next character
          cmp     al, '\'                 ; is current char a backslash?
          je      escapectrl              ; if so, run the subroutine
          jmp     L1_cont                 ; if not, jump to L1_cont and add the char
  
  escapectrl:
          call    handle_ESC              ; run subroutine
          inc     edi
          cmp     [esi], byte 0
          je      L1_end
          jmp     L1_top
  
  L1_cont:
          mov     [edi], al               ; store char in new string
          inc     edi                     ; update dest pointer
          cmp     [esi], byte 0           ; if not null, keep looping
          je      L1_end                  ; end loop if null
          jmp     L1_top                  ; loop if there are more chars
  
  
  
  L1_end:
  
  
          ; print out user input for feedback
          ;
          mov     eax, SYSCALL_WRITE      ; write message
          mov     ebx, STDOUT
          mov     ecx, msg2
          mov     edx, len2
          int     080h
  
          mov     eax, SYSCALL_WRITE      ; write user input
          mov     ebx, STDOUT
          mov     ecx, buf
          mov     edx, [rlen]
          int     080h
  
          ; print out converted string
          ;
          mov     eax, SYSCALL_WRITE      ; write message
          mov     ebx, STDOUT
          mov     ecx, msg3
          mov     edx, len3
          int     080h
  
          mov     eax, SYSCALL_WRITE      ; write out string
          mov     ebx, STDOUT
          mov     ecx, newstr
          mov     edx, [rlen]
          int     080h
  
  
          ; final exit
          ;
  exit:   mov     eax, SYSCALL_EXIT       ; exit function
          mov     ebx, 0                  ; exit code, 0=normal
          int     080h                    ; ask kernel to take over
  
          ; Subroutine begins here.
  
  handle_ESC:
  
          mov     di, [esi]               ; take a copy of the current char
          inc     esi                     ; point to the next char
  
          cmp     di, '7'                 ; is it above 7?
          ja      lowercase               ; if so, skip octal check
  
          cmp     di, '0'                 ; is it below zero?
          jb      lowercase               ; if so, skip octal check
  
  octalinit:
          mov     bl, 0                   ; holds the total for the digit
          mov     cl, 3                   ; count for how many times the loop should run if it's octal
          mov     dh, 8                   ; holds the octal multiple
  
  octalloop:
          mov     ah, [di]                ; store the new char in ah for operations
          sub     ah, 48                  ; convert char to integer
          mul     dl                      ; multiply the octal value by 8
          add     ax, dx                  ; update the total value
          mov     di, [esi]               ; store the next character in di for consideration
          inc     esi                     ; point to the character after that
          cmp     di, '0'                 ; is it below 0?
          jb      lowercase               ; if below, jump out
          cmp     di, '7'                 ; is it above 7?
          ja      lowercase               ; if above, jump out
          dec     cl                      ; count down
          jnz     octalloop               ; loop if needed
          dec     esi                     ; undo the prefetch if no longer looping
          jo      octaloverflow           ; if the overflow flag was set, handle the overflow
          mov     al, bl                  ; stores the finalized value in al
          jmp     done                    ; exit
  
  
  octaloverflow:
          mov     [edi], byte 32          ; makes the second char blank due to error
          jmp     done                     ; not sure if this part is gonna work right
  
  lowercase:
          cmp     di, 'a'                  ; is it a?
          jb      slashprint               ; jump out if it's below a
          cmp     di, 'z'                  ; is it z?
          ja      slashprint               ; jump out if it's above z
          sub     di, 97                   ; convert the lower case letter to decimal
          mov     cl, [bx + di]            ; indexed addressing done here
          cmp     cl, -1                   ; is it -1?
          mov     [edi], cl                ; store the converted char in the string
          inc     esi                      ; point to the spot after
          inc     edi                      ; point to the next entry in the new string
          mov     [edi], byte 32           ; add a blank space in the new string where the lowercase letter was
          jmp     done                  
  
  slashprint:
          cmp     di, '\'                  ; is it another slash?
          jne     errormsg                 ; jump and print an error message
          mov     [edi], byte 92           ; store a slash in the new string
          inc     edi                      ; move to the next position of the new string
          mov     [edi], byte 32           ; make the second char blank since both are slashes
          jmp     done                     ; return
  
  errormsg:
          inc     esi                     ; skip over the character after the slash
  
  
  done:
          ret
  
           ; end Subroutine.
  </code></pre>