因此,我已经让我的ROT13密码做了我想做的事情,但是在最后,命令提示符显示在输出的最后一行。这是我在汇编中的第一个项目,所以我不确定我做错了什么。
发布于 2016-09-24 08:12:37
您的程序不会在输出结束时打印换行符,因此光标退出时位于非空行的末尾。shell不知道这一点,并在那里打印下一个提示符。
echo foo包括一个尾随的换行符,所以当shell打印下一个提示符时,光标已经位于新行的开头。echo -n foo不包括尾随的换行符,所以它将光标留在以foo开头的行的末尾,并且您的提示符被加到上面,就像您的程序一样。将这些回显命令导入hd,以查看它们打印的ASCII字符的十六进制。
因此,解决方案是确保输出以换行符结束(ASCII代码= 10)。您已经在您的msg4: db 10, "Read error", 10字符串中包含了这一点。(它以换行符开头,以一行结尾。)在C中,您会写‘\n nRead错误\n’,但是NASM语法并不是那样工作的。它确实支持反引号字符串中的C样式转义,但对于使用数字常量编写换行符的人来说,这是很典型的。
您的用户输入(从sys_read获得)通常应该以换行符结尾,除非用户在行上键入256个字符,或者使用ctrl提前返回读。(或者类似地,不以换行符结尾的管道输入,因此read命中EOF)。
我开始遵循比较的逻辑,但很快就累坏了。我不知道输入中的换行符会发生什么,但是我怀疑您的代码修改了缓冲区中的换行符。您可能应该避免这种情况,并将它们保持不变。我想您只是将它们添加到您的比较&分支列表中,以避免修改字符。
对于rot13程序来说,这可能比在缓冲区末尾添加额外的换行符更有用,或者调用sys_write再多一次自己打印换行符。
您可以测试您的程序使用strace进行的系统调用。例如,strace ./a.out将解码读()和写()系统调用。
有关更多调试技巧,请参见x86标记wiki的底部。(除了这个,还有很多有用的东西)。
顺便说一句,您可以在xmm寄存器中并行地进行所有这些cmp al, '?'比较,使用SSE2 (将al广播到xmm寄存器的每个元素,以及PCMPEQB具有常量/ PMOVMSKB / test/jnz)。但是,在对标量代码有了很好的处理之前,不要担心这一点。
另一种避免CMP/JCC大鼠巢的方法是使用白名单字母,默认情况下不修改输入字符。。
我不知道为什么你只列出'1',而不是其他数字,或者'+',而不是'-',等等。
这里是如何实现循环的,使用一些“高级”技巧将多个类似条件折叠为单个条件。关于isalpha()的无符号比较技巧的解释,请参阅我在如何访问char数组并将小写字母改为大写字母,反之亦然上的答案。
;; ROT13 alphabetic characters. Copy others unmodified.
;; Untested
L1_top:
movzx eax, [esi] ; get a character
inc esi ; update source pointer
mov edx, eax ; save a copy of the original
or al, 0x20 ; make it lower-case if it's a letter (but we can still detect non-letters after this)
sub al, 'a' ; chars below 'a' will wrap to a high value
cmp al, 'z'-'a'
ja .non_alpha ; jump if the sub wrapped, or the char was greater than 'z'
; input char was alphabetic
sub dl, 13 ; modify the original character
sub al, 13 ; check if that takes us out of the alphabet. Can be a CMP, not SUB if we want.
jnc .nocarry
add dl, 26 ; add 26 if the subtract wrapped
;add al, 26 ; we don't care about the value in al anymore
.nocarry:
; dl = the ROT13'ed character, with its original case
.non_alpha:
mov [edi], dl
inc edi
dec ecx ; I'm not sure what all the cmp ecx,0 in various branches was for. Just do it earlier if necessary.
jnz L1_top最初,我打算在AL中实际计算小写的ROT13 13‘ed字符,然后找出它和原来的小写字符之间的区别,并将其应用于DL。但后来我意识到我可以在早期的分支中有条件地修改DL。
;; after the or al,0x20: mov ah, al ; don't over-do it with upper-half byte registers. False dependencies on AMD, and partial-reg merging stalls or slowdowns on pre-Haswell Intel if you're not careful.
add al, 'a' ; 'a' + al is the lower-cased ROT13 of the input character
sub ah, al ; ah = lcase(orig) - lcase(rot13)
sub dl, ah ; apply that delta to the original in dl
; dl is the original character - 13 (plus 26 if necessary)https://stackoverflow.com/questions/39672274
复制相似问题