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