2011-10-03 132 views
5

Tôi đang nghiên cứu ngôn ngữ lắp ráp MIPS và đã xem qua ví dụ này trong sách và với tôi dường như không chính xác. Nếu đó không phải là sai lầm đầu tiên tôi tìm thấy trong cuốn sách này.Chuyển đổi C thành MIPS - Mảng lồng nhau

Các biến fg đăng ký được giao $s0$s1 tương ứng, địa chỉ cơ sở cho các mảng AB$s6$s7 tương ứng.

Ví dụ mã c là:

f = g - A[B[4]]; 

Và lắp ráp MIPS tương ứng được cung cấp là:

lw $t0, 16($s7) 
lw $s0, 0($t0) 
sub $s0, $s1, $s0 

Từ tôi tìm hiểu trên mã MIPS sẽ tải một số dữ liệu ngẫu nhiên từ bộ nhớ tại địa chỉ cung cấp bởi $t0 và sau đó trừ nó khỏi $s1 và không truy cập vào chỉ mục $t0 của mảng được biểu thị trong $s6.

Các MIPS lắp ráp chính xác từ hiểu biết của tôi sẽ là dọc theo dòng:

lw $t0, 4($s7) 
add $t0, $t0, $s6 
sll $t0, $t0, 2 
lw $s0, 0($t0) 
sub $s0, $s1, $s0 

tôi đúng rằng đây là một lỗi trong cuốn sách hay tôi hiểu lầm gì đó.


Edit: Cố định một lỗi trong mã mips sửa chữa như đã chỉ ra bởi Chris Dodd

+3

Tôi nghĩ bạn đã đúng. Làm tốt! – davin

+1

Giải thích của bạn thật tuyệt vời. Bằng chứng lớn nhất của thực tế là mã đó không làm những gì nó được cho là, là không có đề cập đến bất cứ điều gì của '$ s6', do đó, không có cách nào nó có thể lấy một phần tử từ mảng' A'. – davin

+4

Giả sử mảng A là 4 byte cho mỗi phần tử (vì mảng B có vẻ là - bạn đang sử dụng bù đắp 16 để lấy phần tử 4 và sử dụng lệnh lw để nhận 4 byte), bạn sẽ cần thêm nhân với 4 ở đây quá (hoặc một ca tương đương bằng 2) –

Trả lời

0

Như đã chỉ ra nhiều của tôi đã xảy ra lỗi trong sách. Kể từ khi phát hiện lỗi này, tôi đã tìm thấy một số lỗi như vậy.

-1

Nhưng nó rất tốt có thể là tác giả sao chép mã trước khi thời gian kết nối. Điều này sẽ để ngỏ khả năng rằng các mối liên kết điền vào địa chỉ bộ nhớ của A [] ở vị trí của 0 trong báo cáo

lw $s0, 0($t0) 

trong thực thi chính thức. Tôi không biết nếu MIPS cho phép offsets kích thước đó (có nghĩa là, phạm vi địa chỉ nơi A [] đang được đặt cuối cùng). Điều này tất nhiên là không có cách nào tốt đẹp để giải thích một cái gì đó trong một cuốn sách, phá vỡ một cơ sở riêng của âm thầm và thường không biết những gì đang xảy ra.

+1

Điều này sẽ không hoạt động khi bù đắp được ký kết bù đắp byte 16 bit và '$ s6' về nguyên tắc có thể sử dụng dải địa chỉ 32 bit đầy đủ. Rất nhiều khả năng chỉ đơn giản là một lỗi trong cuốn sách. (Ngoài ra tôi không nghĩ rằng bất kỳ liên kết MIPS sẽ làm loại tối ưu hóa vì nó sẽ thực sự khó chịu với bù đắp tương đối và phải đối phó với trường hợp bù đắp quá lớn) – user786653

+0

Không có trình kết hợp/liên kết sane nào có thể làm điều đó. Hoàn toàn không có sự nhầm lẫn về những gì mà lệnh đó làm. Đó là tải trọng rõ ràng với địa chỉ reg + imm. Nó không giống như một trình biên dịch cho một HLL có thể chèn bất kỳ hướng dẫn nào nó muốn. –

4

Điều này là dành cho bất kỳ ai (có thể là sinh viên CPRE 381), những người có thể vấp ngã khi tìm kiếm một ví dụ điển hình. Mã đã chỉnh sửa của OP vẫn không chính xác. Sự bù đắp trong hàm nạp từ đầu tiên phải là 16. Nó có thể là 4 nếu chiều rộng bộ nhớ là 32 bit, nhưng sau đó sự dịch chuyển/phép nhân sẽ không cần thiết. Giả sử bộ nhớ là 8 bit, các chức năng thêm và thay đổi cần phải được chuyển đổi. Trong mã OP, nó nhân địa chỉ của A [B [4]/4] bằng cách 4. Dịch chuyển/nhân đầu tiên sẽ nhận được chỉ mục chính xác. Mã đúng là:

lw $t0, 16($s7) # gets the value of B[4] 
        # offset could be 4 depending on memory width 
        # but then the shift would not be needed 
sll $t0, $t0, 2 # this multiplies the index by 4 to get the address offset 
add $t0, $t0, $s6 # adds the base address of A and the offset 
lw $t0, 0($t0) # loads the value at the address 
sub $s0, $s1, $t0 # performs subtraction and stores in f 

Trong trường hợp bất kỳ ai nhầm lẫn về toàn bộ chênh lệch 16 so với 4 và cho dù cần phải thay đổi, hãy để tôi giải thích. Nếu chiều rộng bộ nhớ là 32 bit thì toàn bộ số nguyên 32 bit có thể được lưu trữ ở một vị trí bộ nhớ. Nếu trường hợp này xảy ra, thì chỉ mục mảng cũng giống như bù đắp địa chỉ. Tuy nhiên, nếu bộ nhớ chỉ có 8 bit (1 byte) rộng, thì số nguyên 32 bit được lưu trữ trên 4 vị trí bộ nhớ (1 địa chỉ cho mỗi byte). Đây là lý do tại sao bạn cần phải thay đổi chỉ số bằng 2 (hoặc nhân với 4) để có được sự bù đắp địa chỉ chính xác.

Các vấn đề liên quan