计算设置位。 16 位汇编奇偶校验程序
我正在尝试编写一个子程序,该子程序将计算 16 位数字中设置的但数,然后将该数字(设置的位)发送回 AX 中的主程序。主要应显示显示1的个数并判断个数是偶数还是奇数。
我试图通过左移和进位递增来计算 1。问题似乎是,当我回到“main”时,原始输入数字仍然在 AX 中,而不是我在“parity”中得到的计数。我不知道为什么它没有改变。
;===================================================================
; MAIN.ASM
;===================================================================
EXTERN GETDEC$:FAR
EXTERN NEWLINE:FAR
EXTERN PUTSTRNG:FAR
EXTERN PUTDEC$:FAR
EXTERN PUTBIN:FAR
EXTERN PARITY:FAR
;===================================================================
.MODEL LARGE
.STACK 512
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.DATA
NUMBER DW ?
PROMPT DB 'Enter a number: '
BINDISPLAY DB 'Number in binary: '
ONESDISPLAY DB 'Number of 1s: '
ODDDISPLAY DB 'The number of 1s is odd. '
EVENDISPLAY DB 'The number of 1s is even. '
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
.CODE
ASSUME DS:DGROUP
;===================================================================
MAIN PROC
MOV AX,DGROUP ;SET DS-REGISTER TO POINT TO
MOV DS,AX ;DATA SEGMENT
MOV ES,AX ;AND ES ALSO
CALL NEWLINE
MOV DI, OFFSET PROMPT
MOV CX, SIZEOF PROMPT
CALL PUTSTRNG
CALL GETDEC$
CALL NEWLINE
MOV DI, OFFSET BINDISPLAY
MOV CX, SIZEOF BINDISPLAY
CALL PUTSTRNG
CALL PUTBIN
PUSH AX
CALL PARITY
CALL NEWLINE
CALL NEWLINE
MOV DI, OFFSET ONESDISPLAY
MOV CX, SIZEOF ONESDISPLAY
CALL PUTSTRNG
POP AX
CALL PUTDEC$
CALL NEWLINE
SUB DX, DX
MOV BX, 2
DIV BX
CMP DX, 0
JNE ODDS
MOV DI, OFFSET EVENDISPLAY
MOV CX, SIZEOF EVENDISPLAY
CALL NEWLINE
CALL PUTSTRNG
JMP EXIT_PROGRAM
ODDS:
MOV DI, OFFSET ODDDISPLAY
MOV CX, SIZEOF ODDDISPLAY
CALL NEWLINE
CALL PUTSTRNG
EXIT_PROGRAM:
.EXIT
MOV AX, 4C00H
INT 21H
MAIN ENDP
END MAIN
;;===================================================================
; Veronica Kaufman
; CISP 310
; PARITY.ASM
;===================================================================
.MODEL LARGE
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.DATA
ONES_COUNT DW 0
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
.CODE
ASSUME DS:DGROUP
;===================================================================
PARITY PROC FAR PUBLIC USES CX DX DS
POP AX
NUM_LOOP:
CMP AX, 0
JE END_PROGRAM
SHL AX, 1
JC INCREMENT
JMP NUM_LOOP
INCREMENT:
INC ONES_COUNT
JMP NUM_LOOP
END_PROGRAM:
MOV AX, ONES_COUNT
PUSH AX
RET
PARITY ENDP
END PARITY
I am trying to write a subprocedure that will count the number of buts set in a 16bit number, then send that number (bits set) back to the main procedure in AX. The main should display display the number of 1s and determine if the number is even or odd.
I am trying to count the 1s by shifting left and incrementing on carry. The problem seems to be that when I get back to 'main,' the original input number is still in AX rather than the count I got in 'parity.' I don't know why it isn't changing.
;===================================================================
; MAIN.ASM
;===================================================================
EXTERN GETDEC$:FAR
EXTERN NEWLINE:FAR
EXTERN PUTSTRNG:FAR
EXTERN PUTDEC$:FAR
EXTERN PUTBIN:FAR
EXTERN PARITY:FAR
;===================================================================
.MODEL LARGE
.STACK 512
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.DATA
NUMBER DW ?
PROMPT DB 'Enter a number: '
BINDISPLAY DB 'Number in binary: '
ONESDISPLAY DB 'Number of 1s: '
ODDDISPLAY DB 'The number of 1s is odd. '
EVENDISPLAY DB 'The number of 1s is even. '
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
.CODE
ASSUME DS:DGROUP
;===================================================================
MAIN PROC
MOV AX,DGROUP ;SET DS-REGISTER TO POINT TO
MOV DS,AX ;DATA SEGMENT
MOV ES,AX ;AND ES ALSO
CALL NEWLINE
MOV DI, OFFSET PROMPT
MOV CX, SIZEOF PROMPT
CALL PUTSTRNG
CALL GETDEC$
CALL NEWLINE
MOV DI, OFFSET BINDISPLAY
MOV CX, SIZEOF BINDISPLAY
CALL PUTSTRNG
CALL PUTBIN
PUSH AX
CALL PARITY
CALL NEWLINE
CALL NEWLINE
MOV DI, OFFSET ONESDISPLAY
MOV CX, SIZEOF ONESDISPLAY
CALL PUTSTRNG
POP AX
CALL PUTDEC$
CALL NEWLINE
SUB DX, DX
MOV BX, 2
DIV BX
CMP DX, 0
JNE ODDS
MOV DI, OFFSET EVENDISPLAY
MOV CX, SIZEOF EVENDISPLAY
CALL NEWLINE
CALL PUTSTRNG
JMP EXIT_PROGRAM
ODDS:
MOV DI, OFFSET ODDDISPLAY
MOV CX, SIZEOF ODDDISPLAY
CALL NEWLINE
CALL PUTSTRNG
EXIT_PROGRAM:
.EXIT
MOV AX, 4C00H
INT 21H
MAIN ENDP
END MAIN
;;===================================================================
; Veronica Kaufman
; CISP 310
; PARITY.ASM
;===================================================================
.MODEL LARGE
;===================================================================
; D A T A S E G M E N T D E F I N I T I O N
.DATA
ONES_COUNT DW 0
;===================================================================
; C O D E S E G M E N T D E F I N I T I O N
.CODE
ASSUME DS:DGROUP
;===================================================================
PARITY PROC FAR PUBLIC USES CX DX DS
POP AX
NUM_LOOP:
CMP AX, 0
JE END_PROGRAM
SHL AX, 1
JC INCREMENT
JMP NUM_LOOP
INCREMENT:
INC ONES_COUNT
JMP NUM_LOOP
END_PROGRAM:
MOV AX, ONES_COUNT
PUSH AX
RET
PARITY ENDP
END PARITY
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我假设这样做的目的是 PARITY 将在堆栈上获取一个参数,然后修改该参数,将其保留在堆栈上的同一位置:
这不起作用,有两个原因:
CALL
将返回地址压入堆栈。PROC
...USES
生成的序言代码将更多内容推送到堆栈上。当您在
PARITY
中使用POP AX
时,您实际上弹出了一些完全不同的东西(然后将其他东西放回原来的位置) - 可能是由 保存的其他寄存器之一序言。正确执行此操作的选项:
如果您了解此处使用的调用约定,您应该能够找到被推入堆栈的
AX
的位置,很可能在某个小偏移处从 BP 寄存器(我对 MASM 不太熟悉,无法准确了解在这种情况下 PROC 生成的序言代码的作用),并直接加载/存储它。或者,让
PARITY
获取其输入并直接将其输出返回到AX
寄存器中。在这种情况下,您需要删除CALL PARITY
之前的PUSH AX
(输入已经在AX
中)并直接将其放入在CALL
之后(保存返回的结果,稍后将弹出 - 我假设需要保存AX
,因为它可能是被其他调用损坏);并从PARITY
中删除POP AX
和PUSH AX
。I assume that the intent of this is that
PARITY
will take an argument on the stack, and then modify that argument, leaving it in the same place on the stack:This won't work, for two reasons:
CALL
pushes a return address onto the stack.PROC
...USES
pushes more stuff onto the stack.When you
POP AX
insidePARITY
, you're actually popping off something completely different (and then putting something else back in its place) - probably one of the other registers saved by the prologue.Options for doing it right:
If you understand that calling conventions being used here, you should be able to find the location of the
AX
that was pushed onto the stack, most likely at some small offset from theBP
register (I'm not sufficiently familiar with MASM to know exactly what thePROC
-generated prologue code does in this case), and load/store it directly.Or, make
PARITY
take its input and return its output in theAX
register directly. In this case you would need to remove thePUSH AX
before theCALL PARITY
(the input is already inAX
) and put it directly after theCALL
instead (to save the returned result, which will be popped later - I'm assuming thatAX
needs to be saved because it may be corrupted by the other calls); and remove both thePOP AX
andPUSH AX
fromPARITY
.