영어는 모국어가 아닙니다. 입력 오류를 용서하십시오. 여기에 표시 할 코드는 숙제입니다.AX로 저장된 값을 AAM 명령 다음에 2로 나누기 위해 사용하려고합니다. 2 자리 숫자 출력에서 작동하지 않는 이유는 무엇입니까?
나는 실제로 무슨 일이 일어나는지 이해할 필요가있다. 나는 DosBox 0.74 및 TASM 어셈블러에서 인텔 8086 구문을 사용하고 있습니다.
2로 나누어야 할 때 코드의 문제는 삼각형 영역에 있습니다. 참고 : 프로그램은 항상 키보드에서 한 자리 만 읽습니다. 코드를보십시오 (여기에있는 사용자는 부분적으로 보여주기보다는 모든 코드를 보여줄 것을 제안했습니다. 조금 길어 보입니다. 그러나 그가 옳다고 생각합니다. 더 읽기 쉽습니다) [참고 :이 질문을 편집 한 부분 만 문제가있는 코드가 여기에 있었다, 나는 영어의 의견과 메시지를 번역하는 시간이 좀 걸렸지의이 조금 이상, 나는 모든] 번역 할 너무 많은 시간이 없습니다 :
;Segmento de Datos
DATA SEGMENT 'DATA'
LADO1 DB ? ;con el ? se indica que la variable no tiene nada
LADO2 DB ?
LADO3 DB ?
BASE DB ?
ALTURA DB ?
COUNTER DB 0 ;contador para muestra de mensajes
;mensajes ESPECIFICOS
MSG_PRESENTACION DB 10,13,"Este programa calcula los perimetros y areas de algunas figuras geometricas $"
;triangulo
MSG_DIMENSIONES_TRIANGULO DB 10,13,10,13,"Ingrese las dimensiones del triangulo (considere el lado 2 como la BASE)$"
MSG_PERIMETRO_TRIANGULO DB 10,13,"El perimetro del triangulo es: $"
MSG_AREA_TRIANGULO DB 10,13,"El area del triangulo es: $"
;triangulo
;cuadrado
MSG_DIMENSIONES_CUADRADO DB 10,13,10,13,"Ingrese las dimensiones del cuadrado$"
MSG_PERIMETRO_CUADRADO DB 10,13,"El perimetro del cuadrado es: $"
MSG_AREA_CUADRADO DB 10,13,"El area del cuadrado es: $"
;cuadrado
;rectangulo
MSG_DIMENSIONES_RECTANGULO DB 10,13,10,13,"Ingrese las dimensiones del rectangulo$"
MSG_PERIMETRO_RECTANGULO DB 10,13,"El perimetro del rectangulo es: $"
MSG_AREA_RECTANGULO DB 10,13,"El area del rectangulo es: $"
;rectangulo
;otros mensajes GENERALES
MSG_ALTURA DB 10,13,"Introduzca la altura: $" ;sirve para solicitar la altura de varias figuras
MSG_BASE DB 10,13,"Introduzca la base: $"
MSG_LADO DB 10,13,"Ingrese el lado $"
MSG_PUNTO DB ": $" ;sirve para colocar 2 puntos luego del lado
MSG_PRUEBA DB 10,13,10,13,"El valor de prueba es: $"
DATA ENDS
;Segmento de codigo
CODE SEGMENT 'CODE'
ASSUME DS:DATA,CS:CODE ;se le indica al Assembler que DATA es el nombre dado al DATA SEGMENT, y CODE el nombre de CODE SEGMENT
MAIN PROC ;incia el inicio del segmento de codigo
MOV AX,DATA ;hacer disponible/accesible el contenido del DATA SEGMENT al CODE SEGMENT
MOV DS,AX ;inicializar el data segment, debido a limitacion de MOV, se hace con la ayuda de AX
LEA DX,MSG_PRESENTACION ;Mensaje de presentacion/introduccion
CALL printString
;triangulo********
LEA DX,MSG_DIMENSIONES_TRIANGULO ;carga a DX el mensaje 1 (Se le dice al usuario que introduzca los datos del triangulo)
CALL printString
;SOLICITUD DE DATOS ----//----
LEA DX,MSG_ALTURA ;indica al usuario que introduzca la altura del triangulo
CALL printString
CALL readNumber ;se lee del teclado la entrada del usuario mediante este procedimiento (1 digito)
MOV ALTURA,AL
LEA DX,MSG_LADO ;se le dice al usuario que introduzca el lado 1
CALL printString
CALL numberInMessage ;muestra el numero 1 despues del mensaje anterior y DOS PUNTOS para introducccion de datos (solo con fines de formato)
CALL readNumber
MOV LADO1,AL ;mueve valor capturado a la variable
LEA DX,MSG_LADO ;se le dice al usuario que introduzca el lado 2 (la base)
CALL printString
CALL numberInMessage ;muestra el numero 2 despues del mensade de LADO
CALL readNumber
MOV LADO2,AL ;mueve valor capturado a la variable
LEA DX,MSG_LADO ;se le dice al usuario que introduzca el lado 3
CALL printString
CALL numberInMessage ;muestra el numero 3
CALL readNumber
MOV LADO3,AL ;mueve valor capturado a la variable
;PERIMETRO DE TRIANGULO ----//----
ADD AL,LADO2 ;SUMA LADO3(AL) CON CON LADO2 y lo guarda en AL
ADD AL,LADO1 ;SUMA LO ANTERIOR CON LADO1
MOV AH,0 ;borra basura de AH
AAA ;significa ASCII Adjust after Addition
MOV BX,AX ;los registros AH y AL se usan una y otra vez, por tanto para evitar perder sus datos se mueven a BH y BL, esto se hace moviendo AX a BX
LEA DX,MSG_PERIMETRO_TRIANGULO ;lee la direccion efectiva de memoria del mensaje (resultado de la suma) y la carga en DX
CALL printString ;printDigits usa BX para la impresion de los datos
CALL printDigits ;imprime resultado
;AREA DE TRIANGULO ----//----
MOV AL,LADO2 ;multiplicar la base (LADO2) por la altura
MUL ALTURA
AAM
MOV BL,2
AAD
DIV BL
MOV BX,AX
LEA DX,MSG_AREA_TRIANGULO ;mensaje que indica la impresion del area del triangulo
CALL printString
CALL printDigits ;imprime numeros del area del triangulo
;FIN triangulo********
;cuadrado********
LEA DX,MSG_DIMENSIONES_CUADRADO
CALL printString
;SOLICITUD DE DATOS ----//----
LEA DX,MSG_LADO
CALL printString
LEA DX,MSG_PUNTO ;solo con fines de formato, muestra los 2 puntos antes la entrada del usuario
CALL printString
CALL readNumber ;recordemos que la lectura se almacena en AL
MOV LADO1,AL
;PERIMETRO DEL CUADRADO ----//----
MOV AH,4 ;MUL no acepta valores constantes como argumentos, por tanto se mueve a un registro
MUL AH ;multiplicamos la entrada del usuario por 4 y se almacena en AL
MOV AH,0 ;se limpia basura de AH
AAM ;ya explicado, se iran reduciendo comentarios debido a esto, no se omitiran valores y/o situaciones especificas y necesarias para entender
MOV BX,AX ;se mueve porque se trabaja mucho con AX, y evitamos posible perdida de los datos
LEA DX,MSG_PERIMETRO_CUADRADO
CALL printString
CALL printDigits ;imprime lo que esta en BX
;AREA DEL CUADRADO ----//----
MOV AL,LADO1
MUL AL ;multiplicamos la entrada del usuario por el mismo, ya que se desea elevar al cuadrado
MOV AH,0 ;se limpia basura de AH
AAM
MOV BX,AX ;se mueve porque se trabaja mucho con AX, y evitamos posible perdida de los datos
LEA DX,MSG_AREA_CUADRADO
CALL printString
CALL printDigits ;imprime lo que esta en BX
;FIN cuadrado********
;rectangulo********
LEA DX,MSG_DIMENSIONES_RECTANGULO
CALL printString
;SOLICITUD DE DATOS ----//----
LEA DX,MSG_BASE
CALL printString
CALL readNumber
MOV BASE,AL
LEA DX,MSG_ALTURA
CALL printString
CALL readNumber
MOV ALTURA,AL
;PERIMETRO DEL RECTANGULO----//----
MOV AH,2 ;no se puede usar MUL con una consatnte, por tanto se mueve a un registro
MUL AH ;AL contiene la ALTURA, y se multiplica por 2
MOV AH,0 ;se limpia la basura
AAM
MOV BX,AX ;se guarda en otro registro para evitar perdida de datos
MOV AL,BASE
MOV AH,2 ;mismo procedimiento que arriba para multiplicar por un numero constante
MUL AH
MOV AH,0
AAM
ADD BX,AX ;se suma el primer resultado (guardado en BX), con lo ultimo conseguido (guardo en AX), el resultado queda e BX
AAA
LEA DX,MSG_PERIMETRO_RECTANGULO
CALL printString
CALL printDigits
;AREA DEL RECTANGULO ----//----
MOV AL,BASE
MUL ALTURA
MOV AH,0
AAM
MOV BX,AX
LEA DX,MSG_AREA_RECTANGULO
CALL printString
CALL printDigits
;FIN rectangulo********
MOV AH,4CH ;EXIT, termina el programa
INT 21H ;ejecuta la interrupcion
MAIN ENDP ;acaba la rutina principal
;PROCEDIMIENTOS -----------------------------------------------------------------------------------------------------------------------------
printDigits PROC
ADD BX,3030H ;como AH & AL (BH & BL) estan en BCD, se le suman 30 para obtener el valor en ASCII
;primer digito
MOV AH,2 ;se le indica a la interrupcion que haremos una impresion de un CARACTER
MOV DL,BH ;como BH contiene el primer digito, se imprime este primero pasando el valor a DL
INT 21H ;se llama a la interrupcion, que ejecuta lo especificado por AH, tomando como entrada DL
;segundo digito
MOV AH,2 ;nuevamente se le indica una impresion (STANDARD OUTPUT)
MOV DL,BL ;esta vez se pasa el segundo digito
INT 21H ;y se imprime
RET
printDigits ENDP
printString PROC
MOV AH,9 ;se pasa a AH el 9 para indicar que se hara una salida a STANDARD OUTPUT
INT 21H ;interrupcion del DOS, que funciona con el valor del registro AH, el 9 indica STANDARD OUTPUT
RET
printString ENDP
readNumber PROC
MOV AH,1 ;1 en AH indica STANDARD INPUT
INT 21H ;Se usa la interrupcion para tomar entrada del teclado (por instruccion 1 en AH), se retorna lectura a AL
SUB AL,30H ;se convierte de ASCII a numero normal para realizar las operaciones deseadas, el 30 es porque se recibe el numero en BCD desempacado
RET
readNumber ENDP
numberInMessage PROC
ADD COUNTER,1 ;añade 1 a al contador, para nuevos usos es necesario limpiar COUNTER antes de la llamada
MOV BL,COUNTER ;se mueve porque se desea imprimir el contador, y printDigits trabaja con BX
MOV BH,0
CALL printDigits
LEA DX,MSG_PUNTO ;contiene el mensaje de los dos puntos para formato solamente
CALL printString
RET
numberInMessage ENDP
CODE ENDS ;final del segmento de codigo
END MAIN
참고 : "AREA DE TRIANGULO"는 문제가있는 유일한 부분입니다.
모든 숫자 (2 자리 숫자의 출력)에서는 작동하지 않으며 AAM 및 AAD 명령이 문제가 될 것이라고 생각합니다. AX는 2 자리 숫자의 BCD 번호를 필요로하므로 삭제하기로 결정했습니다. AAM 명령을 사용하면 작동하지 않습니다. 그래서 내가 여기에 누락 알고 싶어, 내가이 일을함으로써 얻을 출력 (5, 6 * 6 = 2분의 30 = 15 (5)을 사용하여)된다
The area of the triangle is: 0?
나는 AAD 명령이 일부라고 생각합니다 내가 4, 4와 같은 다른 번호를 사용하는 경우 문제,이 출력 될 것입니다 : 그래서
The area of the triangle is: 08
, 나는 AAD 명령을 삭제하기로 결정하지만, 동작은 동일합니다, 당신은 내게 이유를 알 수 있습니다 ?
시간과 도움을 미리 보내 주셔서 감사합니다. (내 코드에서 뭔가를 할 수있는 또 다른 방법이 있다고 생각하면 어떤 이유에서든 더 배우기를 원합니다)
텍스트가 너무 많으면 더 간결하게 작성하면 더 많은주의를 기울일 수 있습니다. –
실제로 사용중인 프로그램의 전체 소스 코드를 표시하도록 답을 편집하십시오. 그것을 분리 된 조각으로 자른 다음 순서를 뒤섞 지 마십시오. –
이것은 AAM 등을 사용하기위한 [mcve]와 거의 비슷하지 않습니다. 그냥 몇 가지 값을 레지스터로 MOV하고 뭔가를하는 테스트 케이스를 만든다. 그런 다음 실제로 레지스터에있는 내용 (예 : 디버거를 사용하여 검사)을 설명하고 예상하고 싶었거나 예상했던 내용을 설명하십시오. [AAM] (http://www.felixcloutier.com/x86/AAM.html)은 'DIV r8'과 비슷하지만 즉각적인 피연산자가 있고 몫/나머지는 DIV보다 반대 레지스터에 있습니다. 당신의 프로그램이 작동하지 않는다면, 그것을 통해 단계별로 실행하고 당신이 예상했던 것을하지 않는 명령어에 대해서는 insn set reference를 참조하십시오. –