0

So I'm noob on NASM and Linux and I'm doing this program so I can count character on an string given on the Command Line, Before I was trying to create my own procedures to Write and Read on the Terminal, but then my professor told me to start using the macros on the io.mac file that comes with a book from Sirvarama. But when I started using it I got this linking error that I don't know what it Means or how to fix It, so if you could help me, I will appreciate it.

Thanks, sorry for my average sloopy English as you could see in the code and the comments, Spanish is mi first language =D

PD: This is how I'm assembling and linking:

bernal@ubuntu:~/Arqui$ nasm -f elf32 ContChar.asm -l ContChar.lst
bernal@ubuntu:~/Arqui$ ld -m elf_i386 -o ContChar ContChar.o io.o
ContChar.o: In function `ciclo':
ContChar.asm:(.text+0x72): relocation truncated to fit: R_386_16 against `.data'


%include  "io.mac"

.DATA

    ;Equivalencias
     sys_exit:      equ 1
     sys_read:      equ 3
     sys_write:     equ 4
     stdin:         equ 0
     stdout:        equ 1
     stderr:        equ 3


    ;Strings
    ASCII:              db  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',0 ; Letras ASCII
    lenASCII:       equ $ - ASCII   
    myString:           db  'AabBb;Aa_ AhDC',0 ; String a Evaluar
    lenMyString:    equ $ - myString
    yes:                db  'YES',0 ; String Random para debuguear
    lenYes:         equ $ - yes 

    ;Mensajes
    msg1                db "Ingrese algo: ",10,0
    lenMsg1:        equ $ - msg1
    msg2:               db  "Elija Modo:",10,0
    lenMsg2:        equ $ - msg2
    msgCantS:           db "Cantidad de Espacios: "
    lenMsgCantS:    equ $ - msgCantS
    msgCantO:           db "Cantidad de Otros Caracteres: "
    lenMsgCantO:    equ $ - msgCantO

    ;Contadores
    contASCII: times 52     db   0 ; Contador de Letras ASCII
    contSpace:              db   0  ; Contador de Espacios
    contOther:              db   0  ; Contador de Simbolos Extraños

    leninput                db   0

.UDATA
    input:      resb    80
    ;leninput   resb    1
    modo:       resb    1

.CODE

    .STARTUP
    xor ebx, ebx

    PutStr msg1

    mov ecx, input
    mov edx, 300
    call LeerProc
    sub eax,1

    add [leninput],eax

    nwln

    PutStr msg2

    mov ecx,modo
    mov edx,1
    call LeerProc
    pop eax

    mov ebx,input               ;Asigna myString a EBX
    mov ecx,eax                 ;Asigna el largo de myString a ECX 
    ciclo:

        mov AL,[EBX]            ; Pasa el char a AL
        call Proc_Comparar      ; Cuenta el char en el contASCII
        ;call proc_PrintEnter   ;
        inc EBX                 ; Incrementa el EBX para seguir con el siguiente char

    loop ciclo

    nwln

    PutStr ASCII

    nwln

    PutInt contASCII

    nwln

    PutStr msgCantS

    PutStr contSpace

    nwln

    PutStr msgCantO

    PutStr contOther

    nwln

    call Proc_PrintContadores

    jmp Terminar


Proc_Comparar:
    push EBX                    
    push AX                     
    push ecx                    

    ; mov ecx,ebx               ; Pasa el char a ECX
    ; mov edx,1                 ; Asigna el largo de char(1) a EDX
    ; call EscribirProc             ; Muestra el caracter en Pantalla

    cmp AL,'a'                  ; revisa si el char es menor que la letra 'a' minuscula 
    jl  not_lowercase           ; si lo es lo envía a not_lowercase si lo es continua
    cmp AL,'z'                  ; revisa si el char es una letra minuscula al comparar si es mayor que la letra 'z'
    jg  not_letter              ; si es mayor asume que no es una letra y lo envía a not_letter
    jmp lowercase               ; al haber pasado por todo se da cuenta que se trata de una letra minuscula

    lowercase:
        mov EBX,26              ; Se mueve 26 a EBX para que comience en ASCII a partir de las letras minusculas
        cicloL:
            cmp AL,[ASCII+EBX]  ; Compara el char en evaluacion con cada letra ascii minuscula
            jz Found            ; Cuando encuentra el caracter al que es igual salta a Found
            inc EBX             ; Si no lo encuentra aumenta el EBX para seguir comparando con el siguiente caracter
            jmp cicloL          ; Repite el cicloL


    not_lowercase:
        cmp AL,'Z'              ; Revisa si el char es mayor a  la letra 'Z' 
        jg not_letter           ; Si lo es entonces asume que no es una letra pues ya se sabe que no es una letra minuscula y ahora tampoco mayuscula
        cmp AL,'A'              ; Revisa si el char es menor a la letra 'A'
        jl not_letter           ; Si lo es entonces asume que no es una letra pues ya se sabe que no es una letra minuscula y ahora tampoco mayuscula

        mov EBX, 0              ; Asigna un 0 a EBX 
        cicloU:                 ;CicloU hace lo mismo que CicloL solo que con letras mayusculas
            cmp AL,[ASCII+EBX]  
            jz Found
            inc EBX
            jmp cicloU


    not_letter:                 ; Llega aquí cuando no es una letra
        cmp AL,' '              ; Revisa si el char es un Espacio
        jz  Space               ; Si lo es salta a Space
        jmp OtherChar           ; Si no lo es salta a OtherChar

    Space:
        inc byte [contSpace]    ; Incrementa el contador de espacios
        jmp Fin_Comparar        ; Sale del Proceso
    OtherChar:
        inc byte [contOther]    ; Incrementa el contador de otros chars
        jmp Fin_Comparar        ; Sale del Proceso

    Found:
        inc byte [contASCII+EBX] ; Incrementa el contador de la letra que encontró

    Fin_Comparar:               ; Sale del Proceso
        pop  ecx
        pop  AX
        pop  ebx
        ret

Proc_PrintContadores:
    push ecx
    push eax
    push ebx
    push edx

    mov EBX,ASCII               ; Se da la dirección de los caracteres ascii para ver que letra se evalua
    mov ECX,0                   ; Se inicializa en 0 para utilizarlo como indice
    cicloCont:

        mov AL,[contASCII+ECX]  ; Pasa el número del contadorASCII al AL
        cmp AL,0                ; Cmp AL con 0 para saber si se contó la la letra respectiva 
        jg  printASCII          ; Si encuentra algo mayor a 0 procede a imprimirlo
        inc EBX                 ; Incrementa el EBX para continuar con la siguiente letra
        inc ECX                 ; Incrementa el ECX para aumentar el "indice" en los contadores
        cmp ECX,53              ; Se revisa si ya comparo todas las letras ascii ya que en total son 52
        jz  EndPrintCont        ; Si así es termina el Proceso
        jmp cicloCont           ; Repite el cicloCont

    printASCII:
        push ECX

        PutCh [ASCII+ECX]

        PutCh ':'

        Pop ECX
        PutInt [contASCII+ECX]
        Push ECX
        pop ECX

        inc EBX                 ; Incrementa el EBX para continuar con la siguiente letra
        inc ECX                 ; Incrementa el ECX para aumentar el "indice" en los contadores
        cmp ECX,53  
        jmp cicloCont

    EndPrintCont:
        pop  edx
        pop  ebx
        pop  eax
        pop  ecx

        ret

 Proc_printASCII:
         push ecx
         push EBX


         TwoPoints:                 ; Pasa al ecx : para imprimirlos
            mov  ecx,':'
            mov  edx,1
            call EscribirProc
            jmp ImprimirCantidad

         ImprimirCantidad:          ; imprime la cantidad que se almacena en contASCII de la letra respectiva
            mov  ecx,[contASCII+EBX]
            mov  edx,1
            call EscribirProc

         pop  EBX
         pop  ecx

         ret


LeerProc:
    push ebx

    mov eax, sys_read
    mov ebx, stdin
    int 80h

    pop ebx

    ret

proc_PrintYes:
        push edx
        push ecx
        push eax
        push ebx

        mov edx,lenYes  
        mov ecx,yes 
        mov ebx,1   
        mov eax,4   
        int 80h 
        ;call proc_PrintEnter

        pop ebx
        pop eax
        pop ecx
        pop edx 


Terminar:
    .EXIT

The io.mac:

    extern   proc_nwln, proc_PutCh, proc_PutStr
    extern   proc_GetStr, proc_GetCh
    extern   proc_PutInt, proc_GetInt
    extern   proc_PutLInt, proc_GetLInt

    ;;-------------------------------------------------------------------
    %macro  .STARTUP  0
    ;group dgroup .data .bss
            global   _start
    _start:
    %endmacro
    ;;-------------------------------------------------------------------


    ;;-------------------------------------------------------------------
    %macro  .EXIT  0
            mov    EAX,1
            xor    EBX,EBX
            int    0x80
    %endmacro
    ;;-------------------------------------------------------------------


    ;;-------------------------------------------------------------------
    %macro  .DATA 0
            segment .data
    %endmacro
    ;;-------------------------------------------------------------------

    ;;-------------------------------------------------------------------
    %macro  .UDATA 0
            segment .bss
    %endmacro
    ;;-------------------------------------------------------------------

    ;;-------------------------------------------------------------------
    %macro  .CODE 0
            segment .data
            segment .bss
            segment .text
    %endmacro
    ;;-------------------------------------------------------------------


    ;;-------------------------------------------------------------------
    %macro  nwln  0 
            call    proc_nwln
    %endmacro
    ;;-------------------------------------------------------------------


    ;;-------------------------------------------------------------------
    %macro  PutCh  1 
            push    AX
            mov     AL,%1
            call    proc_PutCh
            pop     AX
    %endmacro
    ;;-------------------------------------------------------------------


    ;;-------------------------------------------------------------------
    %macro  PutStr  1 
            push    ECX
            mov     ECX,%1
            call    proc_PutStr
            pop     ECX
    %endmacro
    ;;-------------------------------------------------------------------


    ;;-------------------------------------------------------------------
    %macro  GetStr  1-2 81
            push    ESI
            push    EDI
            mov     EDI,%1
            mov     ESI,%2
            call    proc_GetStr
            pop     EDI
            pop     ESI
    %endmacro
    ;;-------------------------------------------------------------------


    ;;-------------------------------------------------------------------
    %macro  GetCh   1
            push    SI
            xor     SI,SI
    %ifidni %1,AL
            ;inc     SI
            call    proc_GetCh
    %elifidni %1,AH
            mov     SI,1
            call    proc_GetCh
    %else
            push    AX
            call    proc_GetCh
            mov     %1,AL
            pop     AX
    %endif
            pop     SI
    %endmacro
    ;;-------------------------------------------------------------------


    ;;-------------------------------------------------------------------
    %macro  PutInt  1
            push    AX
            mov     AX,%1
            call    proc_PutInt
            pop     AX
    %endmacro
    ;;-------------------------------------------------------------------


    ;;-------------------------------------------------------------------
    %macro  GetInt  1
    %ifnidni %1,AX
            push    AX
            call    proc_GetInt
            mov     %1,AX
          pop     AX
    %else 
            call  proc_GetInt
    %endif
    %endmacro
    ;;-------------------------------------------------------------------

    ;;-------------------------------------------------------------------
    %macro  PutLInt  1
            push    EAX
            mov     EAX,%1
            call    proc_PutLInt
            pop     EAX
    %endmacro
    ;;-------------------------------------------------------------------

    ;;-------------------------------------------------------------------
    %macro  GetLInt  1
    %ifnidni %1,EAX
            push    EAX
            call    proc_GetLInt
            mov     %1,EAX
          pop     EAX
    %else 
            call  proc_GetLInt
    %endif
    %endmacro
    ;;-------------------------------------------------------------------

So here is the result of the objdump -dr ContChar.o:

bernal@ubuntu:~/Arqui$ objdump -dr ContChar.o

  ContChar.o:     file format elf32-i386


  Disassembly of section .text:

  00000000 <_start>:
     0: 31 db                   xor    %ebx,%ebx
     2: 51                      push   %ecx
     3: b9 48 00 00 00          mov    $0x48,%ecx
            4: R_386_32 .data
     8: e8 fc ff ff ff          call   9 <_start+0x9>
            9: R_386_PC32   proc_PutStr
     d: 59                      pop    %ecx
     e: b9 00 00 00 00          mov    $0x0,%ecx
            f: R_386_32 .bss
    13: ba 2c 01 00 00          mov    $0x12c,%edx
    18: e8 7f 01 00 00          call   19c <LeerProc>
    1d: 83 e8 01                sub    $0x1,%eax
    20: 01 05 cf 00 00 00       add    %eax,0xcf
            22: R_386_32    .data
    26: e8 fc ff ff ff          call   27 <_start+0x27>
            27: R_386_PC32  proc_nwln
    2b: 51                      push   %ecx
    2c: b9 58 00 00 00          mov    $0x58,%ecx
            2d: R_386_32    .data
    31: e8 fc ff ff ff          call   32 <_start+0x32>
            32: R_386_PC32  proc_PutStr
    36: 59                      pop    %ecx
    37: b9 50 00 00 00          mov    $0x50,%ecx
            38: R_386_32    .bss
    3c: ba 01 00 00 00          mov    $0x1,%edx
    41: e8 56 01 00 00          call   19c <LeerProc>
    46: 58                      pop    %eax
    47: bb 00 00 00 00          mov    $0x0,%ebx
            48: R_386_32    .bss
    4c: 89 c1                   mov    %eax,%ecx

  0000004e <ciclo>:
    4e: 8a 03                   mov    (%ebx),%al
    50: e8 6f 00 00 00          call   c4 <Proc_Comparar>
    55: 43                      inc    %ebx
    56: e2 f6                   loop   4e <ciclo>
    58: e8 fc ff ff ff          call   59 <ciclo+0xb>
            59: R_386_PC32  proc_nwln
    5d: 51                      push   %ecx
    5e: b9 00 00 00 00          mov    $0x0,%ecx
            5f: R_386_32    .data
    63: e8 fc ff ff ff          call   64 <ciclo+0x16>
            64: R_386_PC32  proc_PutStr
    68: 59                      pop    %ecx
    69: e8 fc ff ff ff          call   6a <ciclo+0x1c>
            6a: R_386_PC32  proc_nwln
    6e: 66 50                   push   %ax
    70: 66 b8 99 00             mov    $0x99,%ax
            72: R_386_16    .data
    74: e8 fc ff ff ff          call   75 <ciclo+0x27>
            75: R_386_PC32  proc_PutInt
    79: 66 58                   pop    %ax
    7b: e8 fc ff ff ff          call   7c <ciclo+0x2e>
            7c: R_386_PC32  proc_nwln
    80: 51                      push   %ecx
    81: b9 65 00 00 00          mov    $0x65,%ecx
            82: R_386_32    .data
    86: e8 fc ff ff ff          call   87 <ciclo+0x39>
            87: R_386_PC32  proc_PutStr
    8b: 59                      pop    %ecx
    8c: 51                      push   %ecx
    8d: b9 cd 00 00 00          mov    $0xcd,%ecx
            8e: R_386_32    .data
    92: e8 fc ff ff ff          call   93 <ciclo+0x45>
            93: R_386_PC32  proc_PutStr
    97: 59                      pop    %ecx
    98: e8 fc ff ff ff          call   99 <ciclo+0x4b>
            99: R_386_PC32  proc_nwln
    9d: 51                      push   %ecx
    9e: b9 7b 00 00 00          mov    $0x7b,%ecx
            9f: R_386_32    .data
    a3: e8 fc ff ff ff          call   a4 <ciclo+0x56>
            a4: R_386_PC32  proc_PutStr
    a8: 59                      pop    %ecx
    a9: 51                      push   %ecx
    aa: b9 ce 00 00 00          mov    $0xce,%ecx
            ab: R_386_32    .data
    af: e8 fc ff ff ff          call   b0 <ciclo+0x62>
            b0: R_386_PC32  proc_PutStr
    b4: 59                      pop    %ecx
    b5: e8 fc ff ff ff          call   b6 <ciclo+0x68>
            b6: R_386_PC32  proc_nwln
    ba: e8 5c 00 00 00          call   11b <Proc_PrintContadores>
    bf: e9 16 01 00 00          jmp    1da <Terminar>

  000000c4 <Proc_Comparar>:
    c4: 53                      push   %ebx
    c5: 66 50                   push   %ax
    c7: 51                      push   %ecx
    c8: 3c 61                   cmp    $0x61,%al
    ca: 7c 16                   jl     e2 <not_lowercase>
    cc: 3c 7a                   cmp    $0x7a,%al
    ce: 7f 2a                   jg     fa <not_letter>
    d0: eb 00                   jmp    d2 <lowercase>

  000000d2 <lowercase>:
    d2: bb 1a 00 00 00          mov    $0x1a,%ebx

  000000d7 <cicloL>:
    d7: 3a 83 00 00 00 00       cmp    0x0(%ebx),%al
            d9: R_386_32    .data
    dd: 74 31                   je     110 <Found>
    df: 43                      inc    %ebx
    e0: eb f5                   jmp    d7 <cicloL>

  000000e2 <not_lowercase>:
    e2: 3c 5a                   cmp    $0x5a,%al
    e4: 7f 14                   jg     fa <not_letter>
    e6: 3c 41                   cmp    $0x41,%al
    e8: 7c 10                   jl     fa <not_letter>
    ea: bb 00 00 00 00          mov    $0x0,%ebx

  000000ef <cicloU>:
    ef: 3a 83 00 00 00 00       cmp    0x0(%ebx),%al
            f1: R_386_32    .data
    f5: 74 19                   je     110 <Found>
    f7: 43                      inc    %ebx
    f8: eb f5                   jmp    ef <cicloU>

  000000fa <not_letter>:
    fa: 3c 20                   cmp    $0x20,%al
    fc: 74 02                   je     100 <Space>
    fe: eb 08                   jmp    108 <OtherChar>

  00000100 <Space>:
   100: fe 05 cd 00 00 00       incb   0xcd
            102: R_386_32   .data
   106: eb 0e                   jmp    116 <Fin_Comparar>

  00000108 <OtherChar>:
   108: fe 05 ce 00 00 00       incb   0xce
            10a: R_386_32   .data
   10e: eb 06                   jmp    116 <Fin_Comparar>

  00000110 <Found>:
   110: fe 83 99 00 00 00       incb   0x99(%ebx)
            112: R_386_32   .data

  00000116 <Fin_Comparar>:
   116: 59                      pop    %ecx
   117: 66 58                   pop    %ax
   119: 5b                      pop    %ebx
   11a: c3                      ret    

  0000011b <Proc_PrintContadores>:
   11b: 51                      push   %ecx
   11c: 50                      push   %eax
   11d: 53                      push   %ebx
   11e: 52                      push   %edx
   11f: bb 00 00 00 00          mov    $0x0,%ebx
            120: R_386_32   .data
   124: b9 00 00 00 00          mov    $0x0,%ecx

  00000129 <cicloCont>:
   129: 8a 81 99 00 00 00       mov    0x99(%ecx),%al
            12b: R_386_32   .data
   12f: 3c 00                   cmp    $0x0,%al
   131: 7f 09                   jg     13c <printASCII>
   133: 43                      inc    %ebx
   134: 41                      inc    %ecx
   135: 83 f9 35                cmp    $0x35,%ecx
   138: 74 37                   je     171 <EndPrintCont>
   13a: eb ed                   jmp    129 <cicloCont>

  0000013c <printASCII>:
   13c: 51                      push   %ecx
   13d: 66 50                   push   %ax
   13f: 8a 81 00 00 00 00       mov    0x0(%ecx),%al
            141: R_386_32   .data
   145: e8 fc ff ff ff          call   146 <printASCII+0xa>
            146: R_386_PC32 proc_PutCh
   14a: 66 58                   pop    %ax
   14c: 66 50                   push   %ax
   14e: b0 3a                   mov    $0x3a,%al
   150: e8 fc ff ff ff          call   151 <printASCII+0x15>
            151: R_386_PC32 proc_PutCh
   155: 66 58                   pop    %ax
   157: 59                      pop    %ecx
   158: 66 50                   push   %ax
   15a: 66 8b 81 99 00 00 00    mov    0x99(%ecx),%ax
            15d: R_386_32   .data
   161: e8 fc ff ff ff          call   162 <printASCII+0x26>
            162: R_386_PC32 proc_PutInt
   166: 66 58                   pop    %ax
   168: 51                      push   %ecx
   169: 59                      pop    %ecx
   16a: 43                      inc    %ebx
   16b: 41                      inc    %ecx
   16c: 83 f9 35                cmp    $0x35,%ecx
   16f: eb b8                   jmp    129 <cicloCont>

  00000171 <EndPrintCont>:
   171: 5a                      pop    %edx
   172: 5b                      pop    %ebx
   173: 58                      pop    %eax
   174: 59                      pop    %ecx
   175: c3                      ret    

  00000176 <Proc_printASCII>:
   176: 51                      push   %ecx
   177: 53                      push   %ebx

  00000178 <TwoPoints>:
   178: b9 3a 00 00 00          mov    $0x3a,%ecx
   17d: ba 01 00 00 00          mov    $0x1,%edx
   182: e8 42 00 00 00          call   1c9 <EscribirProc>
   187: eb 00                   jmp    189 <ImprimirCantidad>

  00000189 <ImprimirCantidad>:
   189: 8b 8b 99 00 00 00       mov    0x99(%ebx),%ecx
            18b: R_386_32   .data
   18f: ba 01 00 00 00          mov    $0x1,%edx
   194: e8 30 00 00 00          call   1c9 <EscribirProc>
   199: 5b                      pop    %ebx
   19a: 59                      pop    %ecx
   19b: c3                      ret    

  0000019c <LeerProc>:
   19c: 53                      push   %ebx
   19d: b8 03 00 00 00          mov    $0x3,%eax
   1a2: bb 00 00 00 00          mov    $0x0,%ebx
   1a7: cd 80                   int    $0x80
   1a9: 5b                      pop    %ebx
   1aa: c3                      ret    

  000001ab <proc_PrintYes>:
   1ab: 52                      push   %edx
   1ac: 51                      push   %ecx
   1ad: 50                      push   %eax
   1ae: 53                      push   %ebx
   1af: ba 04 00 00 00          mov    $0x4,%edx
   1b4: b9 44 00 00 00          mov    $0x44,%ecx
            1b5: R_386_32   .data
   1b9: bb 01 00 00 00          mov    $0x1,%ebx
   1be: b8 04 00 00 00          mov    $0x4,%eax
   1c3: cd 80                   int    $0x80
   1c5: 5b                      pop    %ebx
   1c6: 58                      pop    %eax
   1c7: 59                      pop    %ecx
   1c8: 5a                      pop    %edx

  000001c9 <EscribirProc>:
   1c9: 50                      push   %eax
   1ca: 53                      push   %ebx
   1cb: b8 04 00 00 00          mov    $0x4,%eax
   1d0: bb 01 00 00 00          mov    $0x1,%ebx
   1d5: cd 80                   int    $0x80
   1d7: 5b                      pop    %ebx
   1d8: 58                      pop    %eax
   1d9: c3                      ret    

  000001da <Terminar>:
   1da: b8 01 00 00 00          mov    $0x1,%eax
   1df: 31 db                   xor    %ebx,%ebx
   1e1: cd 80                   int    $0x80
  • We will also need `io.mac`. Presumably it is loading an address into a 16 bit register. Alternatively, do `objdump -dr ContChar.o` and see where you have a `R_386_16` relocation. – Jester Apr 20 '15 at 10:21
  • Try `PutInt [contASCII]` instead of `PutInt contASCII`. You are trying to print the address not the value. Still, that `io.mac` is quite a mess of 16 and 32 bit code. – Jester Apr 20 '15 at 11:16
  • Also [Relocation Truncated to Fit error in NASM x86\_64](https://stackoverflow.com/q/2720161) for the specific linker error message. – Peter Cordes Mar 08 '21 at 10:36

0 Answers0