Hola :), primero gracias por tomarse el tiempo para leer esta pregunta ;D
Tengo este código ensamblador de NASM que realice para probar una teoría de condicionales
el chiste es que no puedo hacerlo correr debido a un problema que me sale:
%include "io.inc"
%macro print 1
push eax
push ecx
mov eax, %1
mov ecx, -1
while:
add ecx, 1
cmp byte [eax+ecx], 0
jmp PRINT_CHAR [eax+ecx]
jne while
pop ecx
pop eax
%endmacro
%macro strcpy 2
push eax
push ecx
push edx
mov eax, %1
mov edx, %2
mov ecx, -1
.while:
add ecx, 1
cmp byte [eax+ecx], 0
mov [edx+ecx], byte [eax+1]; al parecer en esta linea de codigo esta el error :-[
jne .while
je print edx
pop edx
pop ecx
pop eax
%endmacro
;segment data
section .data
msg db "Hola", 13, 0
msg2 db " ", 0
section .text
global CMAIN
CMAIN:
xor eax, eax
call strcpy msg, msg2
ret 0
Error:
C:\Users\Windows\AppData\Local\Temp\SASM\program.asm:40: error: invalid combination of opcode and operands
gcc.exe: error: C:\Users\Windows\AppData\Local\Temp\SASM\program.o: No such file or directory
No se que hacer para solucionarlo, programo en windows bajo el IDE de SASM
Agradezco toda la ayuda ;D
Edit:
En la linea 25 era:
mov [edx+ecx], byte [eax+ecx]; al parecer en esta linea de codigo esta el error :-[
:xD
Cita de: alienxz77b en 18 Octubre 2021, 08:00 AM
C:\Users\Windows\AppData\Local\Temp\SASM\program.asm:40: error: invalid combination of opcode and operands
Estas usando la sintaxis de invoke:
https://docs.microsoft.com/en-us/cpp/assembler/masm/invoke?view=msvc-160 (https://docs.microsoft.com/en-us/cpp/assembler/masm/invoke?view=msvc-160)
Mas informacion sobre la dicotomia entre call e invoke:
http://www.asmcommunity.net/forums/topic/?id=29146 (http://www.asmcommunity.net/forums/topic/?id=29146)
En la linea cuarenta.
Eso traducido a un call corriente con una convencion de llamada de C:
https://en.wikipedia.org/wiki/X86_calling_conventions (https://en.wikipedia.org/wiki/X86_calling_conventions)
Seria:
Citar
push addr msg2
push addr msg
call strcpy
Deberia funcionar, aunque no lo probe.
Suerte. :-*
PD:
Si quisieras usar invoke:
Citar
invoke strcpy msg, msg2
Hola gracias por responder ;D, al parecer sigue tirando el mismo error :-\
Si, el mov de la linea 25 no es factible pero te recomiendo revisar y depurar todo, no encuentro el sentido a usar eax + 1 en cada iteracion (eso en este caso copia el segundo caracter de una cadena siempre).
Esto es equivalente a lo que intentabas:
mov bl, [eax+1]
mov [edx+ecx], bl
PD. invertiste el orden de los parametros de strcpy, el primero deberia ser el destino y el segundo la fuente.
Ya arregle el código :D:
%include "io.inc"
%macro print 1
push eax
push ecx
mov eax, %1
mov ecx, -1
while:
add ecx, 1
cmp byte [eax+ecx], 0
jmp PRINT_CHAR [eax+ecx]
jne while
pop ecx
pop eax
%endmacro
%macro strcpy 2
push eax
push ecx
push edx
push SI
mov edx, %1
mov eax, %2
mov ecx, -1
.while:
add ecx, 1
cmp byte [eax+ecx], 0
mov SI, [eax+ecx]
mov [edx+ecx], SI
jne .while
pop SI
pop edx
pop ecx
pop eax
%endmacro
;segment data
section .data
msg db "Hola", 13, 0
section .bss
msg2 resb 100
section .text
global CMAIN
CMAIN:
xor eax, eax
strcpy msg2, msg
print msg2
ret 0
Gracias por su ayuda a todos los que respondieron ;D
Nos vemos ;)
Bien, ahora tiene logica la copia pero sigue teniendo exactamente el mismo bug que en el otro hilo al escribir con print y es opuesto al standard de C el strcpy.
Según Wikipedia:
https://es.wikipedia.org/wiki/Strcpy (https://es.wikipedia.org/wiki/Strcpy)
La sintaxis de strcopy esta bien ;D
Codigo sin bugs o algo parecido (puede que tenga errores :()
%include "io.inc"
%macro print 1
push eax
push ecx
mov eax, %1
mov ecx, -1
while:
add ecx, 1
cmp byte [eax+ecx], 0
jmp PRINT_CHAR [eax+ecx]
jne while
pop ecx
pop eax
%endmacro
%macro strcpy 2
push eax
push ecx
push edx
push SI
mov edx, %1
mov eax, %2
mov ecx, -1
.while:
add ecx, 1
cmp byte [eax+ecx], 0
mov SI, [eax+ecx]
mov [edx+ecx], SI
jne .while
pop SI
pop edx
pop ecx
pop eax
%endmacro
;segment data
section .data
msg db "Hola", 0
section .bss
msg2 resb 100
section .text
global CMAIN
CMAIN:
xor eax, eax
strcpy msg2, msg
print msg2
ret 0
Mala mia, lo cambiaste y ahora si el primer parametro es el destino y el segundo la fuente, el bug del print sigue ahi, escribe el 0 terminador.
De hecho solo se pueden imprimir cadenas usando el terminador nulo como en C ;D
No, una cosa es ENCONTRARLO para frenar y otra muy diferente escribir el 0, eso hace tu codigo y ninguna funcion para escribir una cadena en pantalla lo hace ;) ¿Para que le sacaste el 13 a msg? ;D ;D ;D ¿Para que no pasara esto?
(https://i.ibb.co/mN3qDL5/bug.png)
¿Crees que si llamo a printf con "Hola\r" como parametro pasa eso acaso? Necesitaria llamar a putc con el 0 para que lo escribiera y pasara lo mismo que con tu macro print.
PD. Si se puede. char nnts[] = { 'N', 'E', 'W', 'B', 'I', 'E', 0xCC, 0xCC };
printf("%.*s", 6, nnts);
Cita de: Eternal Idol en 25 Octubre 2021, 09:22 AM
%.*s
Perdona el cambio de tema, Eternal Idol, pero una pregunta rapida... ¿Esto que sintaxis tiene?
https://www.cplusplus.com/reference/cstdio/printf/
"* The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted."
Cita de: Eternal Idol en 25 Octubre 2021, 13:57 PM
https://www.cplusplus.com/reference/cstdio/printf/
"* The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted."
No sabia que se podia limitar eso... Un riesgo menos.
Gracias
Cita de: marax en 25 Octubre 2021, 17:29 PM
No sabia que se podia limitar eso... Un riesgo menos.
Gracias
De nada ::)
Creo que esta es la solucion:
%include "io.inc"
%macro print 1
push eax
push ecx
mov eax, %1
mov ecx, 0
while:
add ecx, 1
cmp byte [eax+ecx], 0
jmp PRINT_CHAR [eax+ecx-1]
jne while
pop ecx
pop eax
%endmacro
%macro strcpy 2
push eax
push ecx
push edx
push SI
mov edx, %1
mov eax, %2
mov ecx, -1
.while:
add ecx, 1
cmp byte [eax+ecx], 0
mov SI, [eax+ecx]
mov [edx+ecx], SI
jne .while
pop SI
pop edx
pop ecx
pop eax
%endmacro
;segment data
section .data
msg db "Hola", 13, 0
section .bss
msg2 resb 100
section .text
global CMAIN
CMAIN:
xor eax, eax
strcpy msg2, msg
print msg2
ret 0
;D
Sigue teniendo fallos; SI es un registro 16 bits por lo que la condicion para terminar el bucle se basa en un byte pero lees y escribis 2 bytes por cada iteracion, eso carece de sentido, es ineficiente (sobrescribe datos) y lleva a problemas, por ejemplo, teniendo una cadena vacia:
msg db 0
oops db "BUG", 0
El strcpy no funciona bien, copia la B de oops en msg2 :rolleyes: Estas leyendo mas alla de los limites de la cadena.
Ademas si por ejemplo en lugar de usar msg2 como parametro a print uso msg. ¿Que crees que pasa? Lee un buffer que no deberia leer: oops.
(https://i.imgur.com/ytnbQes.png)