我正在尝试使用nasm来重写Peter Abel撰写的“IBM PC ASSEMBLY LANGUAGE AND PROGRAMMING”(第15版)中的汇编程序。这里是关于缓冲输入的演示,在144页的第8章中给出。
该程序相当于C编程
char name[20];
scanf("Name?%s", &name);
/*print the input name in the middle of the screen 25 * 80*/
....
我的重写程序是:
;file: A08CTRNM.asm
segment data
paralist:
maxlen: db 20 ;The maximum length of the string will be 20
actulen: resb 1 ;Which character we have inputed now
buffer: times 20 db 0 ;The buffer where the string is buffered
;end of paralist
prompt: db "Name?", "$"
segment code
..start:
mov ax, data
mov ds, ax
mov es, ax
mov ss, ax
mov sp, stacktop
call setCursor
call input
call clearScreen
cmp byte [actulen], 0 ;Name entered?
je exit ;no, exit
call center ;set bell and '$' and center
call displayStr ;Display name
exit:
mov ax, 0x4c00
int 0x21
segment stack stack
resb 64
stacktop:
input:
push ax
push dx
mov ah, 09h ;Print the prompt
mov dx, prompt
int 21h
mov ah, 0ah ;Request keyboard
mov dx, paralist
int 21h
pop dx
pop ax
ret
center:
mov bx, actulen ;Replace ENTER with BELL
mov byte [buffer+bx], BELL ;[buffer+bx] was ENTER, and now is BELL
mov byte [buffer+bx+1], '$' ;Set display delimiter
mov dl, [actulen] ;Locate the center column (40 - strlen / 2)
shr dl, 1 ;devide length by 2
neg dl ;reverse sign
add dl, 40 ;add 40 (DL:DH Colume:Row)
mov dh, 12 ;center row
call setCursor
ret
displayStr:
mov ah, 09h
mov dx, buffer
int 21h
ret
clearScreen:
pusha
mov ax, 0600h
mov bx, 30 ;color attribute
mov cx, LEFT_CORNER
mov dx, RIGHT_CORNER
int 10h
ret
setCursor:
mov ah, 02h
mov bh, 00h
int 10h
ret
我在linux下用
编译它$ nasm -fobj A08CTRNM.asm -o a.obj
并将其链接到dosemu下的turbo c 2.0中的链接“tlink.exe”
c:\tlink a.asm
但是链接器抱怨了什么
Fixup overflow in module A08CTRNM.ASM at CODE:000D, target=000D:0006
Fixup overflow in module A08CTRNM.ASM at CODE:0010, target=0010:0006
Fixup overflow in module A08CTRNM.ASM at CODE:0013, target=0013:0006
Fixup overflow in module A08CTRNM.ASM at CODE:0020, target=0020:0006
当我运行可执行文件“a.exe”时,出了点问题
c:\a ->
Name?
Invalid Opcode at 00B1 02A9 0202 001B 0000 0000 0000 0000 0000 0000 0000 0000 00
你能告诉我如何解决该计划吗?
答案 0 :(得分:2)
您的筹码有两个问题。
ss
初始化为data
,而不是stack
。解决方案:在mov ax, stack
mov ss, ax
input
开始的所有代码都被放入堆栈段。这导致了打印的错误。解决方案:将堆栈段移动到文件的底部,或切换回代码段。答案 1 :(得分:0)
我认为杰斯特已经确定了你的主要问题......但还有其他人......
我知道手册中的示例可以做到这一点,但是如果你正确地声明你的堆栈 - 你做了什么,除了不切换回segment code
之外(第二个stack
很重要! ) - DOS将为您初始化ss
和sp
。不应该做任何伤害,但你根本不需要这样做。 (您需要初始化ds
和es
,而不是ss:sp
)我不知道为什么在手册中说明了这一点。
在center:
子例程中,您执行:mov bx, actulen
。这是actulen
的地址(地址的偏移部分)。将其添加到buffer
的地址会使您在树林中出现"。你想要内容 - [actulen]
。但它只是一个字节!所以把它移到' bl' ,并确保bh
清晰明确(您需要bx
全部来形成地址)。 movzx bx, byte
[actulen]`也会这样做。
在您的clearScreen:
子功能中,popa
之后您未能pusha
。
即使用户未输入任何内容,我也不确定[actulen]
是否为零。我记得,int 21h/0Ah
包括在" count"中结束输入的CR。返回 - 所以[actulen]
将是1,而不是0.(一个相当小的问题)
如果你想在Linux中进行链接(但对于DOS程序),Anthony Williams' Alink可以为Linux构建。它需要对源代码进行一些更改。您可能最好在DosBox中使用Tlink,但如果您愿意,可以在Linux中完成。
您的帖子说您正在尝试关联.asm文件,但我认为这只是" posto"。
快乐聚会!