堆栈相对寻址 - 解释和问题

时间:2017-03-22 01:22:40

标签: pep8-assembly

我会尽量缩短序言。

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

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

我已经查阅了教科书,通过电子邮件发送给我的教授(回复待定,但我就像一条带骨头的狗 - 我不能单独完成这项功课,直到完成),并尝试了我能想到的所有可能的排列。这个示例几乎与pep / 8帮助中包含的示例相同(我认为图6.34中的哪一个是布尔转换示例),除了字符存储在#1cs而不是#2d中。

无论如何,问题的核心是每当我尝试在uprcse函数中访问ch2时,程序就会从堆栈中获取返回地址。据我所知,我这样做与示例相同,不幸的是,找不到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                  

2 个答案:

答案 0 :(得分: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'。而不是重新加载A并比较'z',你可以比较'z' - 'a'(25):

         CPA   25,i
         BRGT  else

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

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

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

答案 1 :(得分:0)

一切!跟进这篇文章。

我和教授谈过,他澄清了我的错误 -

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