ROT13装配密码

时间:2016-09-24 03:47:12

标签: linux assembly x86 nasm rot13

所以我的ROT13密码非常符合我的要求,但最后命令提示符显示在与最后一行输出相同的行上。这是我在大会的第一个项目,所以我很不确定我做错了什么。

1 个答案:

答案 0 :(得分:0)

您的程序在输出结束时不会打印换行符,因此当光标退出时,光标位于非空行的末尾。 shell不知道这一点,并在那里打印下一个提示。

echo foo包含一个尾部换行符,因此当shell打印下一个提示时,光标已经在新行的开头。 echo -n foo不包含尾随换行符,因此它会将光标留在以foo开头的行的末尾,并且您的提示会被添加到该行,就像您的程序一样。将这些echo命令传递到hd以查看它们打印的ASCII字符的hexdump。

因此,解决方案是确保输出以换行符结尾(ASCII代码= 10)。您已在msg4: db 10, "Read error", 10字符串中使用了该字符串。 (它以换行符开头,也以一行结束。)在C语言中,你写“" \ n读取错误\ n"”,但NASM语法不能这样做。它确实支持反引号字符串中的C风格转义,但人们用数字常量编写换行符是典型的。

您的用户输入(您从sys_read获得)通常应以换行符结尾,除非用户在一行上键入256个字符,或使用ctrl-D提前读取返回。 (或类似的管道输入,不会以换行结束,因此读取命中EOF)。

我开始遵循比较的逻辑,但它很快就累了。我不确定输入中的换行符会发生什么变化,但我怀疑您的代码会修改缓冲区中的换行符。你应该避免这种情况,并保持不变。我想你只是将它们添加到你的比较列表中。分支不要修改的字符。

对于rot13程序来说,这可能比在缓冲区末尾添加额外的换行符更有用,或者在一段时间内调用sys_write来自行打印换行符。

您可以使用strace测试程序进行的系统调用。例如strace ./a.out将解码您所做的read()和write()系统调用。

有关更多调试提示,请参阅标记wiki的底部。 (除此之外还有很多有用的东西)。

顺便说一下,你可以在xmm寄存器中并行地进行所有cmp al, '?'比较,使用SSE2(广播到xmm寄存器的每个元素,PCMPEQB用常量/ PMOVMSKB / test / jnz)。但是,除非您对标量代码有良好的处理,否则不要担心。

另一种避免CMP / JCC老鼠窝的方法是白名单字母字符,默认情况下输入字符不加修饰。

我不确定你为什么只将'1'列入黑名单,而不是列入其他数字,或'+'而不是'-',等等。

以下是我如何实施您的循环,其中包含一些"高级"将多个类似条件折叠成单一条件的技巧。请参阅我在How to access a char array and change lower case letters to upper case, and vice versa上的答案,了解isalpha()的无符号比较技巧。

;; 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字符,然后找出它与原始的低级字符之间的区别,并将其应用于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)