2016-01-16 24 views
1

我使用汇编语言(nasm)做了一个程序来进行重叠块传输,即如果我的数组中有一个数组包含'10,20,30,40,50'(不含引号)然后重叠例如2个元素后,我的结果数组应包含'10,20,10,20,30,40,50'(不含引号)。但我的问题是,当我显示我的结果数组时,它只显示'10,20,10,20,30'(不含引号)。我无法弄清楚这个问题。下面显示的是我的代码。任何帮助将不胜感激。无法在程序集中执行重叠块传输

%macro disp 2        ; Display macro 
mov rax,1 
mov rdi,1 
mov rsi,%1 
mov rdx,%2 
syscall 
%endm 

%macro accept 2        ; Accept Data 
mov rax,0 
mov rdi,0 
mov rsi,%1 
mov rdx,%2 
syscall 
%endm 

global _start   

section .data        ; Data Section 
arr db 10h,20h,30h,40h,50h 
msg1: db "",10,"Input array is",10 
len1: equ $-msg1 
msg2: db "",10,"Output array is",10 
len2: equ $-msg2 
msg3: db "Enter the number to be overlapped",10 
len3: equ $-msg3 

section .bss        ; Bss Section 
arr1 resb 10 
ar1 resb 10 
ar2 resb 10 
cn resb 2 



section .text        ; Text Section 
_start:         ; Tell linker entry point 

disp msg3,len3          
accept cn,2       ; Accept No. of overlaps to be done from user 

mov cl,[cn]       ; Convert the cn from ASCII 
sub cl,'0'       ; to Decimal 

mov rsi,arr 
mov rdi,arr1 


up: mov al,[rsi]       ; Copy the contents from arr to arr1 for cn times 
mov [rdi],al 
inc rsi 
inc rdi 
dec cl 
jnz up 

mov rsi,arr       ; Now copy the contents again from starting 
mov cl,5 

up_a: mov al,[rsi] 
mov [rdi],al 
inc rsi 
inc rdi 
dec cl 
jnz up_a 

mov rsi,arr       ; Convert to ASCII 
mov rdi,ar1 
mov rdx,5 
call asci 

mov rsi,arr1       ; Convert to ASCII 
mov rdi,ar2 
mov rdx,10 
call asci 

disp msg1,len1 
disp ar1,10 

disp msg2,len2 
disp ar2,10 

mov rax,60 
mov rdi,0 
syscall 


asci: 

up1: mov al,[rsi]  ;Move the first element pointed by rsi into al register 
    mov cl,2  ;The loop counter (there are 2 digits) 

up2: rol al,4  ; Rotate the contents of al 4 bits to the left. What were 
        ; previously the most significant bit will now be in 
        ; the least significant bit of al. This is done because 
        ; we want to print the most significant digit first. 
    mov bl,al  ; Make a copy of the rotated version of al. 
    and al,0Fh  ; Keep the least significant bit of al and set all other 
        ; bits of al to 0. 
    cmp al,09h  ; al will now be in the range 0..15. Is it greater than 9? 
    ja dn1   ; ..if so, jump to dn1. 
    add al,30h  ; al was in the range 0..9. The characters '0'..'9' are encoded as 
        ; 30h..39h in ASCII, so add 30h to convert into a character. 
    jmp dn2   ; We're done with this case. 

dn1: add al,37h  ; al is in the range 10..15. The characters 'A'..'F' are encoded as 
         ; 41h..46h in ASCII, so add 37h to convert into a character. 

dn2: mov [rdi],al  ; Store the character in the buffer pointed to by rdi. 
    mov al,bl  ; Restore al to the value it had right after the rol. So on the 
        ; next iteration we'll be processing what were originally the 
        ; second most significant bit, and so on. 
    inc rdi   ; Increment the buffer pointer. 
    dec cl   ; Decrement the loop counter. 
    jnz up2   ; Repeat for all 2 digits. 

     inc rsi   ; rsi now points to the next location 
    dec rdx   ; Decrement the loop counter 
    jnz up1   ; Repeat for all 5 array elements 

ret 
+0

你的'asci'函数是如何工作的?为什么不只是加'al','0',而不是你的旋转/掩码/比较/'加'al','7'?另外,在普通的ABI中,rbx是保存的,但是你可以使用bl作为临时寄存器。你确定你没有写出数组的最后?例如**也许你第二次调用'asci'会从第一次调用结束,因为你只使用了10个字节的输出缓冲区。**我还没有弄清楚你的代码在哪里检测数组的长度(这取决于重叠的量)。 –

+0

我已经尝试过将'al','0''转换为ASCII码,但问题在于我使用的是数组。此外,如果我使用该代码,它会显示分段错误。所以我用上面的书面程序转换成ASCII。我想你要明白,ASCII功能是如何工作的,如果是这样的话然后再看看节目,我已经添加了注释,使其更好地理解。现在针对你的第二个问题,你是否建议在我的第一个ASCII调用之后使用系统调用? – Paras

+0

哦,对了,转换为十六进制数字需要在'0-9'与'A-F'一个分支,我明白这是关于现在你已经改善了意见。对于缓冲区处理:如果您转换/打印,转换/打印,而不是转换,转换/打印,打印,则不需要两个单独的ASCII缓冲区。但是你仍然需要保留适量的空间,就像Score_Under的答案指出的那样。 –

回答

2

您的重叠复印工作正常。不工作的是你如何调用显示程序。

首先,你只分配了10个字节的输出,当你复制一个10字节数组的十六进制表示进去(所以你需要20个字节!)

其次,你只印刷10个字节。由于我们将长度更改为20,因此您应该更改打印长度。

这里是统一的diff形式的变化:

--- orig.s 2016-01-16 19:55:33.268099503 +0000 
+++ modified.s 2016-01-16 19:58:24.952600505 +0000 
@@ -28,7 +28,7 @@ 
section .bss        ; Bss Section 
arr1 resb 10 
ar1 resb 10 
-ar2 resb 10 
+ar2 resb 20 
cn resb 2 


@@ -77,7 +77,7 @@ 
disp ar1,10 

disp msg2,len2 
-disp ar2,10 
+disp ar2,20 

mov rax,60 
mov rdi,0 

尽管有对数组长度错误和列的打印,您已经有了在调用asci功能正确的长度。

+0

谢谢你,它的工作原理。 – Paras