我在 16 位 x86 asm 中有這個重復的迭代程序
rec_loop:
mul bx ; constant value of 0x11bf
add ax, 0x4743
loop rec_loop
它運行了幾次,但對于我們的例子,假設它運行了 3 次,現在完成后我得到dx:ax并且需要恢復ax該程式的初始值(初始dx值為 0)。乍一看,我們可以看到關于 dx 的資訊在這個程序中丟失了,因為用新mul的覆寫了最后dx一個。
如果可能的話,我正在尋找一種方法來扭轉這個程序,當然假設上面的代碼不能改變。
如果我忘記解釋某事或沒有提供有關問題的足夠詳細資訊,請告訴我,我會回答。
uj5u.com熱心網友回復:
計算 x n 1 := (a * x n c) mod m, a = 0x11bf, c = 0x4743, m= 2 16形成一個偽亂數生成器。具體來說,一個周期為 2 11的線性同余生成器。顯然這不是一個高質量的 PRNG,但對于只需要看起來有點隨機的資料的用例來說可能就足夠了。我注意到該問題并未說明使用此代碼的背景關系。
x i的序列(這里是在 中連續生成的AX)可以通過使用模乘逆 a逆來反轉,如下所示:x n-1 = a逆* (x n - c) mod m。在這種情況下,模乘逆是0xde3f。
請注意,DX在向后計算中不需要 的值,并且在序列中的任何點都可以根據AX需要輕松確定。下面的乘法逆的確定使用基于定義的樸素方法。對于較大的運算元大小,這是非常低效的,人們可能希望使用擴展歐幾里得演算法。
簡單的 C99 代碼,用于試驗乘法逆的計算和 中的值序列的反轉AX:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define X_0 (0xc001)
#define ITERS (3)
uint32_t modular_inverse (uint32_t a, uint32_t m)
{
for (uint32_t x = 1; x < m; x ) {
if (((a % m) * (x % m)) % m == 1) {
return x;
}
}
printf ("no inverse found\n");
return 0;
}
uint16_t umul16_lo (uint16_t a, uint16_t b)
{
return (uint16_t)(a * b);
}
uint16_t umul16_hi (uint16_t a, uint16_t b)
{
return (uint16_t)(((uint32_t)a * b) >> 16);
}
int main (void)
{
const uint16_t a = 0x11bf; // multiplier of PRNG
const uint16_t c = 0x4743; // additive offset of PRNG
const uint32_t m = 0x10000U; // modulo of PRNG
uint16_t a_inverse;
a_inverse = modular_inverse (a, m);
printf ("a_inverse = x\n", a_inverse);
const uint16_t bx = a;
uint16_t dx = 0;
uint16_t ax = X_0;
printf ("starting values: ax=x dx=x bx=x\n", ax, dx, bx);
printf ("forward computation\n");
for (int i = 0; i < ITERS; i ) {
dx = umul16_hi (ax, bx);
ax = umul16_lo (ax, bx) c;
}
printf ("after %d iterations: ax=x dx=x bx=x\n", ITERS, ax, dx, bx);
printf ("backward computation\n");
for (int i = 0; i < ITERS; i ) {
ax = umul16_lo (ax - c, a_inverse);
}
printf ("after %d iterations: ax=x\n", ITERS, ax);
return EXIT_SUCCESS;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/424411.html
