0

我会尽量保持序言简短。

是的,这本质上是“帮助我完成大学作业”,但我非常坚持这一点(我们在第 10 小时,在这里)。

目标 - 编写一个汇编程序,将一个字符作为输入并将该字符输出为大写。

我已经复习了这本教科书,给我的教授发了电子邮件(正在等待回复,但我就像一条有骨头的狗——在完成之前我不能把这个功课搁置一旁),并尝试了我能想到的所有可能的排列方式。此示例与 pep/8 帮助中包含的示例几乎相同(我认为是图 6.34?无论哪个是布尔转换示例),只是字符存储在 #1cs 而不是 #2d 中。

无论如何,问题的核心是,每当我尝试在 uprcse 函数中访问 c​​h2 时,程序都会从​​堆栈中获取返回地址。据我所知,我所做的与示例相同,不幸的是,无法找到 pep/8 的良好在线资源(感谢 Python,将您的标准称为 pep8 ...),所以我在我可以多么疯狂地用谷歌搜索。

请在下面查看我的代码,并随时通过您自己的 pep8 运行它并告诉我我到底做错了什么。

请不要觉得需要做堆栈溢出的事情并指出我的代码中的每一个小缺陷——我知道这在 uprcse 函数中可能会有不同的分支。我的意思是,如果这就是你获得踢腿/因果报应的方式,你可以稍作修正,但是......嗯。

         BR      main          
;
;******* char uppercase(char ch)
retVal:  .EQUATE 2           ;returned value #1c
ch2:     .EQUATE 1           ;formal parameter #1c
uprcse:  LDBYTEA ch2,sx    ;if ((ch >= 'a')
if:      CPA     'a',i         
         BRLT    else        
         LDBYTEA ch2,s         ;   && (a <= 'z'))
         CPA     'z',i     
         BRGT    else        
then:    LDBYTEA ch2,s      ;   return changed
         SUBA    'a',i
         ADDA    'A',i
         STBYTEA retVal,s    
         RET0                
else:    LDBYTEA ch2,d     ;   return unchanged
         STBYTEA retVal,s    
         RET0         

;******* main ()
ch:     .EQUATE  0           ;local variable #1c
main:    SUBSP   1,i         ;allocate #ch 
         STRO    msg0,d         ;cout << "Enter character, Zack" << endl
         CHARI   ch,s       ;cin >> ch  
         LDBYTEA ch,s        
         STBYTEA     -2,s        ;store the value of age
         SUBSP   2,i         ;push #retVal #ch2 
         CALL    uprcse      ;ch = (uppercase(ch)
         ADDSP   2,i         ;pop #ch2 #retVal 
         LDBYTEA -1,s        ;load retVal
         STBYTEA     ch,s
         CHARO   ch,s          ;cout << ch << endl
         CHARO   '\n',i        
         ADDSP   1,i         ;deallocate #ch 
         STOP                
msg0:    .ASCII "Enter character\n\x00"
         .END                  
4

2 回答 2

0

全部!跟进这篇文章。

我与教授交谈,他澄清了我的错误-

我犯的错误是我没有在 .EQUATE 中为大写函数设置正确的值。我应该使用 2 和 3 作为值,而不是 1 和 2。我还需要在大写函数的开头使用 LDA 0x0000,i 清除累加器。当此作业结束并评分时,我将发布整个工作源代码。

于 2017-03-23T11:00:19.557 回答
0

我要做那个stackoverflow的事情。对不起。

在您的main, 阅读字符后,您犯了一个小错误:

         STBYTEA -2,s        ;store the value of age
         SUBSP   2,i         ;push #retVal #ch2 

您存储到 SP-2,然后从 SP 中减去 2。这会使您的代码容易受到由中断引起的罕见问题的影响,其中可能会触发中断(将数据写入堆栈底部)然后返回,从而损坏您的数据。

当您编写汇编时,您应该始终在实际使用您“分配”的内存之前进行框架调整。

在这段代码中,

         CALL    uprcse      ;ch = (uppercase(ch)
         ADDSP   2,i         ;pop #ch2 #retVal 
         LDBYTEA -1,s        ;load retVal
         STBYTEA     ch,s

你做相反的事情,在访问你的结果之前添加到 SP。同样的理论也适用。在解除分配之前提取数据。

    CALL     uprcse
    LDBYTEA  0,s       ; 0 because now return value is above SP
    STBYTEA  ch,s
    ADDSP    2,i

在你的uprcse函数中,我认为你有一个简单的算术错误:

;******* char uppercase(char ch)
retVal:  .EQUATE 2           ;returned value #1c
ch2:     .EQUATE 1           ;formal parameter #1c
uprcse:  LDBYTEA ch2,sx    ;if ((ch >= 'a')

在此代码中,您定义ch2为 SP+1。我认为您应该使用+2。此外,您可以通过调整堆栈框架以立即包含本地存储来简化您的生活:

ch:      .EQUATE  4       ; formal parameter `ch` #1c
;old-sp  .EQUATE  2       ; 2 bytes for return address
temp     .EQUATE  0       ; Not actually used, just to show locals

uprcse:  SUBSP    2,i     ; Adjust stack frame for locals
         LDA      ch,s

请注意,在大多数计算机(不是全部!)上,“比较”操作是“减法”的同义词。有时它是“减去但不存储”。其他时候是“减去并确保设置标志”。但总的来说,减法和比较经常相关。您可以利用它来发挥自己的优势:

         CPA    'a',i    
         BRLT   else

此时,A 寄存器包含 ch-'a'。您可以与 'z'-'a' (25) 进行比较,而不是重新加载 A 并与 'z' 进行比较:

         CPA   25,i
         BRGT  else

最后,ASCII 被设计(故意!)在大小写字母之间有 32 个字符。这使得小写只有一个 ch+32 的距离。或者你可以设置32位。同样,要从低到高,只需减去 32,或清除 32 位。

         LDBYTEA ch2,s
         SUB     32,i
         STBYTEA ch2,s
else:
         RET2           ; Remember temp?

在这种情况下,我假设您可以重新使用ch2形式参数的存储作为返回结果。特别是因为ch2除非它是小写,否则结果将是相同的,在这种情况下我们会调整它。

于 2017-03-22T02:47:15.730 回答