Blog

  • Chapter 19: Don’t Ask, Don’t Tell

    It was Sunday morning, and Pastor Mark was in quite a foul mood. Of the 200 citizens of Podunk, about 50 of them attended church every Sunday, most of the time. The only thing different on this Sunday was that Chad and Stacy walked in together and sat together. No one would have noticed except for the fact that it was common for Chad to sit with Matthew, John, and Luke in the same pew. Luke eyed Chad and Stacy suspiciously, with a hint of jealousy.

    Pastor Mark started speaking as he usually did for his sermon:

    “Hello brothers and sisters in Christ, my message today is about an abomination that is infecting our culture, politics, religious institutions, and even the military. As some of you know, in 1993 the U.S. military enacted the Don’t Ask, Don’t Tell policy, which allowed homosexuals into the military as long as they remained secretive about their lifestyle. It is times like this when we must remember God’s judgment on this depraved activity. Please turn with me to Genesis chapter 18 starting at verse 17. We shall read about God’s judgment on the cities of Sodom and Gomorrah,” said Mark.


    Genesis 18:17 And the LORD said, Shall I hide from Abraham that thing which I do ;

    18 Seeing that Abraham shall surely become a great and mighty nation, and all the nations of the earth shall be blessed in him?

    19 For I know him, that he will command his children and his household after him, and they shall keep the way of the LORD, to do justice and judgment; that the LORD may bring upon Abraham that which he hath spoken of him.

    20 And the LORD said, Because the cry of Sodom and Gomorrah is great, and because their sin is very grievous;

    21 I will go down now, and see whether they have done altogether according to the cry of it, which is come unto me; and if not, I will know.

    22 And the men turned their faces from thence, and went toward Sodom: but Abraham stood yet before the LORD.

    23 And Abraham drew near, and said, Wilt thou also destroy the righteous with the wicked?

    24 Peradventure there be fifty righteous within the city: wilt thou also destroy and not spare the place for the fifty righteous that are therein?

    25 That be far from thee to do after this manner, to slay the righteous with the wicked: and that the righteous should be as the wicked, that be far from thee: Shall not the Judge of all the earth do right?

    26 And the LORD said, If I find in Sodom fifty righteous within the city, then I will spare all the place for their sakes.

    27 And Abraham answered and said, Behold now, I have taken upon me to speak unto the Lord, which am but dust and ashes:

    28 Peradventure there shall lack five of the fifty righteous: wilt thou destroy all the city for lack of five? And he said, If I find there forty and five, I will not destroy it.

    29 And he spake unto him yet again, and said, Peradventure there shall be forty found there. And he said, I will not do it for forty’s sake.

    30 And he said unto him, Oh let not the Lord be angry, and I will speak: Peradventure there shall thirty be found there. And he said, I will not do it, if I find thirty there.

    31 And he said, Behold now, I have taken upon me to speak unto the Lord: Peradventure there shall be twenty found there. And he said, I will not destroy it for twenty’s sake.

    32 And he said, Oh let not the Lord be angry, and I will speak yet but this once: Peradventure ten shall be found there. And he said, I will not destroy it for ten’s sake.

    33 And the LORD went his way, as soon as he had left communing with Abraham: and Abraham returned unto his place.

    Genesis 19:1 And there came two angels to Sodom at even; and Lot sat in the gate of Sodom: and Lot seeing them rose up to meet them; and he bowed himself with his face toward the ground;

    2 And he said, Behold now, my lords, turn in, I pray you, into your servant’s house, and tarry all night, and wash your feet, and ye shall rise up early, and go on your ways. And they said, Nay; but we will abide in the street all night.

    3 And he pressed upon them greatly; and they turned in unto him, and entered into his house; and he made them a feast, and did bake unleavened bread, and they did eat.

    4 But before they lay down, the men of the city, even the men of Sodom, compassed the house round, both old and young, all the people from every quarter:

    5 And they called unto Lot, and said unto him, Where are the men which came in to thee this night? bring them out unto us, that we may know them.

    6 And Lot went out at the door unto them, and shut the door after him,

    7 And said, I pray you, brethren, do not so wickedly.

    8 Behold now, I have two daughters which have not known man; let me, I pray you, bring them out unto you, and do ye to them as is good in your eyes: only unto these men do nothing; for therefore came they under the shadow of my roof.

    9 And they said, Stand back. And they said again, This one fellow came in to sojourn, and he will needs be a judge: now will we deal worse with thee, than with them. And they pressed sore upon the man, even Lot, and came near to break the door.

    10 But the men put forth their hand, and pulled Lot into the house to them, and shut to the door.

    11 And they smote the men that were at the door of the house with blindness, both small and great: so that they wearied themselves to find the door.

    12 And the men said unto Lot, Hast thou here any besides? son in law, and thy sons, and thy daughters, and whatsoever thou hast in the city, bring them out of this place:

    13 For we will destroy this place, because the cry of them is waxen great before the face of the LORD; and the LORD hath sent us to destroy it.

    14 And Lot went out, and spake unto his sons in law, which married his daughters, and said, Up, get you out of this place; for the LORD will destroy this city. But he seemed as one that mocked unto his sons in law.

    15 And when the morning arose, then the angels hastened Lot, saying, Arise, take thy wife, and thy two daughters, which are here; lest thou be consumed in the iniquity of the city. {are here: Heb. are found} {iniquity: or, punishment}

    16 And while he lingered, the men laid hold upon his hand, and upon the hand of his wife, and upon the hand of his two daughters; the LORD being merciful unto him: and they brought him forth, and set him without the city.

    17 And it came to pass, when they had brought them forth abroad, that he said, Escape for thy life; look not behind thee, neither stay thou in all the plain; escape to the mountain, lest thou be consumed.

    18 And Lot said unto them, Oh, not so, my Lord:

    19 Behold now, thy servant hath found grace in thy sight, and thou hast magnified thy mercy, which thou hast shewed unto me in saving my life; and I cannot escape to the mountain, lest some evil take me, and I die :

    20 Behold now, this city is near to flee unto, and it is a little one: Oh, let me escape thither, (is it not a little one?) and my soul shall live.

    21 And he said unto him, See, I have accepted thee concerning this thing also, that I will not overthrow this city, for the which thou hast spoken. {thee: Heb. thy face}

    22 Haste thee, escape thither; for I cannot do any thing till thou be come thither. Therefore the name of the city was called Zoar. {Zoar: that is, Little}

    23 The sun was risen upon the earth when Lot entered into Zoar. {risen: Heb. gone forth}

    24 Then the LORD rained upon Sodom and upon Gomorrah brimstone and fire from the LORD out of heaven;

    25 And he overthrew those cities, and all the plain, and all the inhabitants of the cities, and that which grew upon the ground.

    26 But his wife looked back from behind him, and she became a pillar of salt.

    27 And Abraham gat up early in the morning to the place where he stood before the LORD:

    28 And he looked toward Sodom and Gomorrah, and toward all the land of the plain, and beheld, and, lo, the smoke of the country went up as the smoke of a furnace.


    After Mark had finished reading the story of God destroying the cities of Sodom and Gomorrah, half of the people in the sanctuary were asleep. It was then that Chad’s friend John decided to ask some questions.

    “Excuse me, pastor, but what is this story really about, and how does it relate to the Don’t Ask, Don’t Tell policy of 1993?” asked John.

    Know in the Biblical Sense

    “The men of Sodom wanted to have sex with the angels who were staying at Lot’s house. They thought they were men and wanted to perform sexual acts,” said Mark.

    “It never said anything in chapter 19 about them wanting to have sex with the men. It said they wanted to know the men. I assume they wanted to know who the strangers were”, said John.

    "No, it was know in the biblical sense. Like in Genesis 4, when Adam knew his wife, Eve, and she got pregnant and gave birth to her son, Cain.


    Genesis 4:1 And Adam knew Eve his wife; and she conceived, and bare Cain, and said, I have gotten a man from the LORD.


    “Okay, that makes sense in light of that, but how was I supposed to know what you are talking about when the King James Bible doesn’t even agree with what you are trying to say”, said John.

    “Just shut up and listen, John. I am the Pastor, and I know things you don’t. Let me finish and then ask questions later, you’re interrupting my sermon”, said Mark.

    “Hey, Pastor Mark, don’t talk that way to my friend John”, said Chad.

    “I can talk to him however I want. It’s my show, and I can do whatever I want,” said Mark.

    "Your show? Then perhaps it is time for a commercial break! John, I can help with this. First, the King James Bible is useless for understanding sexual matters because it doesn’t use our language. Some versions of the Bible, such as the International Standard Version, speak in the way we would say it, and the men of Sodom did want to have sex with Lot’s guests.


    Genesis 19:5 They called out to Lot and asked, “Where are the men who came to visit you tonight? Bring them out to us so we can have sex with them!” – International Standard Version.


    “Thanks, Chad, but how are we supposed to know which version of the Bible we need to understand these Bible stories?” asked John.

    “That’s a very good question, John. Hey Pastor, what do you think about Biblical versus modern language? Any advice for my friend John here?” asked Chad.

    “I only use the King James Bible because I can get copies cheaply and it is out of copyright, so I don’t have to pay royalties for using it. But I recommend using whatever helps you in your studies. In any case, the point of the story is that the people in the city were so wicked that men wanted to have sex with men. Because Lot was righteous and tried to protect his guests, they warned him to flee so that his family could be spared from God’s judgment,” said Mark.

    “I must disagree, Pastor. Lot was not righteous by any stretch of the imagination. Consider verse 8, where he offered his virgin daughters to the men of Sodom and asked them to rape his daughters instead of his guests. He doesn’t sound like he is any better than the wicked men of Sodom”, said Chad.

    “Look, Chad, I must agree with you on that. Lot was not perfect, but even he recognized that raping women is not as sinful as men raping other men. He was offering his daughters as the lesser of two evils”, said Mark.

    “How does this story relate to the military policy of Don’t Ask, Don’t Tell?” asked Chad.

    “My message is simple: as a society, the United States of America has become too accepting of homosexuals and their depraved lifestyle. We must vote against politicians who are lenient on sexual sin, or else God will have no choice but to judge us just as he did Sodom and Gomorrah,” said Mark.

    “You think God will rain fire and brimstone on us for voting the wrong way?” asked Chad.

    “Precisely. That is why we must be reminded of God’s judgment against wickedness,” said Mark.

    “Pastor, I am not so sure this policy is all that bad. People should be able to keep their sexual lives private, and nobody should ask them questions they are not prepared to answer, and they should not tell anyone who they cannot trust. Perhaps such discussions should be left out of the military. Perhaps it is a policy we should follow outside of the military as well.”

    “Madness, Chad, we must know who the homosexuals are so we can put them to death, just as it states in Leviticus 20:13”, said Mark.

    “Leviticus 20:13: If a man also lie with mankind, as he lieth with a woman, both of them have committed an abomination: they shall surely be put to death; their blood shall be upon them.”

    “But what if they don’t lie but tell the truth?” asked John.

    “Not that kind of lie, John, once again, this is a reference to having a man having sex with a man as a man would with a woman”, said Mark.

    “But if a man doesn’t have a vagina, then another man couldn’t possibly have sex with him, and so there could never have been a person who matched the description of Leviticus 20:13”, said John.

    “We will discuss such matters privately; we are getting off topic”, said Mark.

    “But I still have questions!” said John.

    “Okay, fine, one more question, then we wrap up for today, and I will continue this series of sermons”, said Mark.

    “Suppose a man is drafted into the Army for a war, but he is a pacifist who does not want to kill people. Suppose he does a homosexual act so that he can get kicked out of the military where he never wanted to be in the first place. What exactly is a homosexual act, and what is the least sinful act he can commit to both be forgiven by God and yet also banned from the military for life?” said John.

    “I suppose he could kiss another man, or something like that, but why so many questions? Are you a homosexual?” asked Mark.

    The Exodus of Podunk Church

    “Look, Pastor, I don’t really know what a homosexual is, or even what a homosexual act is supposed to be. However, if I get drafted into the military, I want to know what my options are to get out. I am also trying to understand your sermon and this Bible story. You seem really vague, as if you are choosing your words carefully, or maybe you just really don’t know what you are talking about,” said John.

    “ENOUGH!, I won’t allow my preaching to be disrespected, and I will not entertain such dangerous ideas. I want anyone who is either a homosexual or friends with a homosexual to leave my church, and preferably, leave my town and country,” said Mark.

    “Your church? Your town? Your country? Sorry, Pastor, but we are all God’s children and this whole planet is our home, but if you intend to kill homosexuals, then perhaps Don’t Ask, Don’t Tell is the policy I will follow from now on,” said Chad.

    It was then that Chad stood up and walked out. Stacy walked out beside him. Then John and Matt followed after a minute. Gabby followed them all to see what Chad would do next. After all, the children of Podunk were expecting Chad and Luke to play soccer with them and teach them Bible stories, like they usually did after the regular Sunday service.

    About The Story of Chad

    The chapter you just read is from my book:

    The Story of Chad: The man who changed the heart of Podunk

    Right now, the book is only available digitally because it is not completed yet. However anyone who purchases it on Leanpub now or in the future gets free updates as I add more to it.

    The story is a fictional novel meant to inspire people to think differently about Christianity and navigating complex moral issues. It is written to be relatable to others with similar experiences I have been through.

  • Chapter 18: Alliance of Convenience

    “Stacy, what did you want to talk about?” asked Chad.

    “I wanted to ask something. Chad, would you officially be my boyfriend?” asked Stacy.

    “What do you mean by boyfriend? Does that change anything between us?” asked Chad.

    “No, it doesn’t change anything between us. We will still be the same great friends we already are. However, I think we should seriously consider spending the rest of our lives together. It solves several problems,” said Stacy.

    “What do you mean by problems?” asked Chad.

    “I have two problems. The first is that my dad and I just had a fight over you. He disagrees with what you are teaching the children about the Bible. Because I fully support what you are doing, he accuses me of being in love with you and taking your side because I am blinded by my feelings. Second, I am tired of church women trying to hook me up with their sons or having guys like Luke repeatedly ask me out on a date when I have made it very clear I am not interested. It would be convenient if people already knew I had a boyfriend,” said Stacy.

    “So, are you in love with me, or is it just socially convenient for people in town to think we are together?” asked Chad.

    “I’m gonna be real with you, Chad. I have never met a Christian as true as you. You spend every second thinking about the right move both in Chess and in life by asking what Jesus would do. If I am falling in love with you, it is because of the person you are and who you have chosen to be. I do love you, but I am not sure in what way. I only ask that we explore where this goes,” said Stacy.

    “And if something goes wrong, will it ruin our friendship?”

    “What could possibly go wrong, Chad? But I promise you that if all else fails, we will remain friends, and I still want to help you explore what it means to be a true Christian and teach the children with you.”

    Chad and Stacy had been talking so long that they completely forgot Matt was still sitting there watching them. He got up from his chair and started walking towards the door.

    “Hey Matt, where do you think you are going?” asked Chad.

    “I will let you two lovebirds finish your conversation privately. I won’t get in the way,” said Matt.

    “Thanks, Matt, but just remember, if Stacy and I have a wedding, you will be my best man,” said Chad.

    “Thanks, Chad. Good night”, said Matt.

    “Are you already planning our wedding, Chad?” said Stacy.

    “A good Chess player needs to think a few moves ahead of the current position”, said Chad.

    “Well said, Chad, but does this mean you agree to be my boyfriend?” asked Stacy.

    "Stacy, you are the only girl in this town I know that is a Vegan who loves animals as much as I do. I also know that you have changed since I met you. You wanted to keep your life private and hesitated to join Soccer Sundays because you didn’t want to be in the spotlight. Here you come asking me, the most famous guy in the town, to be your boyfriend. So yes, I agree, but this is an irreversible decision, and I hope you are prepared for a real commitment, instead of an alliance of convenience.

    “What do you mean, irreversible?” asked Stacy.

    “Your life will change forever once we are known as a couple. You won’t shake the reputation of being the only girlfriend of Chad Isaac, the watermelon and tofu-eating soccer star. Do you think you can handle the gossip that will happen in this small town where everybody and their dog knows what is happening?” asked Chad.

    “I am prepared for whatever comes our way, but what do you mean that I am your only girlfriend?” asked Stacy.

    “Believe me, Stacy, plenty of girls have flirted with me, and their parents have tried to play matchmaker, but I can tell when people are only interested in my money or social influence. I turn them all down because I need someone who matches my values, and you are the only one who talks to me like a person instead of dropping hints and doing the flirty eyes.”

    “Speaking of which, be wary of my father. Reputation and money are all he cares about, but I am not like my father. I hope you understand that”, said Stacy.

    “I figured that out the day you slapped Pastor Mark and told him off after he tried to fire me from being a volunteer Bible story teller. I know you are different, and I am glad you talked to me about this,” said Chad.

    Chad and Stacy continued to talk about many things that night, including their relationship and future things they could do for the animals and the children of Podunk.

  • Chapter 17: Knowing the Right Move

    Chad and Matt were playing Chess at Chad’s house. Not too many people knew about Chad’s obsession with the game of Chess or why it was so important to him, although his profession was Soccer.

    “Queen’s pawn to d4!” said Chad with weird enthusiasm.

    “Then I will also move my Queen’s pawn two spaces forward”, said Matt.

    “In that case, I will move my C-file pawn two squares to c4”, said Chad.

    “You’re going to let me take that pawn?” said Matt.

    “Only if you want to”, said Chad.

    “I can’t resist! Fine, I choose to capture the pawn on c4!” said Matt.

    “Perfect, now I move my king’s pawn to e4”, said Chad.

    “And I move my knight to f6”, said Matt.

    “That’s fine by me because I can capture your c4 pawn with my light-squared bishop”, said Chad.

    “I see you captured back the pawn, but next I capture your e4 pawn with my knight. You’re still a pawn down, and the game just barely started”, said Matt.

    “I’m not worried about the e4 pawn; I have a bigger plan in mind. I move my knight to f3”, said Chad.

    “Come on, Chad, I thought you were good at this game! All I have to do is move my bishop to g4, and now your knight can’t move because I will capture your queen with the bishop if it does”, said Matt.

    “I already know that, but I am still moving my knight to e5 anyway!” said Chad.

    “You’re crazy, Chad. I take your queen on d1 with my bishop”, said Matt.

    “And I move my bishop from c4 to f7. Checkmate!” said Chad.

    The Chess game was over after only 13 moves:

    1. d4 d5
    2. c4 dxc4
    3. e4 Nf6
    4. Bxc4 Nxe4
    5. Nf3 Bg4
    6. Ne5 Bxd1
    7. Bxf7#

    d4-d5-c4-dxc4-e4-nf6-bxc4-nxe4-nf3-bg4-ne5-bxd1-bxf7.png

    “Wait…what have you done?! My king has nowhere to go!” said Matt.

    “Yes, you can’t take the bishop on f7 or move to d7 because the knight protects both those spots. It doesn’t matter that I lost the queen”, said Chad.

    “Where did I go wrong, and what should I have done differently?” said Matt.

    “If you had moved your king’s pawn one square, the bishop could never have reached the f7 square. However, your eyes were on capturing my queen, and you forgot to leave an escape for your king”, said Chad.

    “How did you figure out how to do tricks like this?”

    “I just sacrificed two pawns and my queen to win the game. It turns out that it doesn’t matter how many pieces I lose as long as I have a way to trap your king. You could say that my queen sacrificed itself much like Jesus did for us”, said Matt.

    “Chad, are you seriously making an allegory about Jesus using a Chess game? Don’t you ever stop?” said Matt.

    “I don’t know what to tell you, Matt. These things just come out of my mouth. I plan my Chess moves better than the things I say”, said Chad.

    They both laughed at how absurd it sounded for Chad to say things without thinking.

    “Chad, I have to disagree. It seems like you put a lot of effort into everything you say and do. How do you always know the right move?” said Matt.

    “You flatter me too much, Matt. Yes, I usually plan my words and my Chess moves, but I don’t always know the right move. Chess is simple, but sometimes real life is complex and I just plain don’t know. Sometimes I pray about it or try to read something I remember from the life of Jesus that is relevant”, said Chad.

    “Can you name one time you didn’t know the right move?” said Matt.

    “Yeah, a couple weeks ago…” Chad started to say until

    Knock Knock

    “Someone is at the door”, said Chad.

    “Expecting anyone?” said Matt.

    “No, it is unusual to have guests with no warning. Maybe I am in trouble for something,” said Chad before answering the door.

    Chad opened the door, and outside was Stacy.

    “Hi Chad, I want to talk. Are you busy at the moment?” asked Stacy.

    “Never too busy for my friends. Matt is already here, and I was just about to answer a question Matt asked me. Actually, your timing is perfect!” said Chad.

    “What do you mean, Chad?” Stacy said, looking extremely confused.

    “Stacy, sit down, and you’ll find out! Matt, to answer your question, the last time I didn’t know the right move was after the Sunday when Luke brought hot dogs and told the story of Noah’s Ark and the flood from Genesis chapter 6. I questioned whether I should even be involved or just quit participating in the Soccer and Sunday School ministry.”

    “Why did you want to quit?” asked Matt.

    “Because I wasn’t sure whether I was any more qualified to teach the Bible to these children than Luke was. Obviously he prefers the Old Testament and stories of God’s judgment, but I prefer the New Testament and Jesus’ teachings of love, forgiveness, generosity, and sacrifice. How can I know I am right?” said Chad.

    “So what happened? How did you decide to continue?” said Matt.

    “Stacy and I met by accident in the library, and she told me about how a butterfly has to be born again and become a new creature. That is when it hit me that Jesus is what the New Testament is about. Even now I can’t be sure if my beliefs are correct, but I decided to follow my heart and the example set by Jesus. I don’t believe in murder, nor do I think God commanded the killing of animals or humans as was written in the Old Testament.”

    “But do you believe in the concept of sacrifice? Did Jesus really have to die for us?” said Matt.

    “I don’t know if he had to, or if there may have been another way, but there is a difference between sacrificing someone else to save your own life and sacrificing yourself to save others. If it is what Jesus wanted to do, who am I to disagree?”

    “Just like the queen sacrifice in Chess”, said Matt.

    “Correct, Matt, perhaps for some reason Jesus sacrificed himself to win a game that we don’t even know the rules of. I just hope Jesus is a good Chess player and that he knows the right move even when I don’t,” said Chad.

    Stacy looked at the Chessboard for a minute.

    “I see…so that’s what happened”, said Stacy.

  • chastelib Java Edition

    I translated my C library of functions into a Java class. This will help make future programs easier to port. I am very rusty on the Java language but it is a fairly old and reliable language. There are some cool things about Java, even though my favorite language will always be C.

    main.java

    /*
     Java Port of Chastity's library of standard functions
    
     This Java class is a library of functions written by Chastity White Rose.
     The functions are for converting strings into integers and integers into strings.
    
     Core Four Functions
    
     intstr: Convert an integer to a string in bases 2 to 36
     strint: Convert a string in bases 2 to 36 to an integer
     putstr: Print a string to standard output
     putint: Print an integer using intstr and then putstr
    
    */
    public class main
    {
    
     public static void main(String[] args)
     {
      String s="Official test suite for the Java version of chastelib.\n";
      int a=0,b=0x10;
    
      radix=16;
      int_width=1;
    
      putstr(s);
    
      b=strint("100"); /*convert string to an integer*/
      if(strint_errors!=0) /*if there are errors, print some messages and exit the program*/
      {
       putstr("Input string passed to strint function contains errors.\n");
       putstr("Fix the invalid characters or radix and try again.\n");
       return;
      }
    
      while(a<b)
      {
       radix=2;
       int_width=8;
       putint(a);
       putstr(" ");
       radix=16;
       int_width=2;
       putint(a);
       putstr(" ");
       radix=10;
       int_width=3;
       putint(a);
    
       if(a>=0x20 && a<=0x7E)
       {
        putstr(" ");
        putchar(a);
       }
    
       putstr("\n");
       a++;
      }
    
      putstr(s);
     }
    
     static void putstr(String s)
     {
      System.out.print(s);
     }
    
     static void putchar(int i)
     {
      String s=""; /*create empty string*/
      s=(char)i+s; /*add char of i to string*/
      putstr(s);   /*print the string*/
     }
    
     /*radix or base for integer output. 2=binary, 8=octal, 10=decimal, 16=hexadecimal*/
     static int radix=2;
     /*default minimum digits for printing integers*/
     static int int_width=1;
    
     static String intstr(int i)     /*Chastity's supreme integer to string conversion function*/
     {
      int width=0;                   /*the width or how many digits including prefixed zeros are printed*/
      int c=0;                       /*byte for the current character*/
      String s="";
      while(i!=0 || width<int_width) /*loop to fill the string with every required digit plus prefixed zeros*/
      {
       c=i%radix;                    /*get the remainder of division by the radix or base*/
       i/=radix;                     /*divide the input by radix*/
       if(c<10){c+='0';}             /*convert digits 0 to 9 to the ASCII character for that digit*/
       else{c=c+'A'-10;}             /*for digits higher than 9, convert to letters starting at A*/
       s=(char)c+s;                  /*prefix return string with this digit's character*/
       width++;                      /*increment the width so we know when enough digits are saved*/
      }
     return s;                      /*return this string to be used by putstr,printf,std::cout or whatever*/
    }
    
    
     static void putint(int i)
     {
      putstr(intstr(i));
     }
    
     static int strint_errors = 0; 
    
    
     static int strint(String s)
     {
      int i=0;
      int c;
      strint_errors = 0; /*set zero errors before we parse the string*/
      if( radix<2 || radix>36 ){ strint_errors++; putstr("Error: radix is out of range!\n");}
      int x=0;
      while(x<s.length())
      {
       c=s.charAt(x);
       if( c >= '0' && c <= '9' ){c-='0';}
       else if( c >= 'A' && c <= 'Z' ){c-='A';c+=10;}
       else if( c >= 'a' && c <= 'z' ){c-='a';c+=10;}
       else if( c == ' ' || c == '\n' || c == '\t' ){break;}
       else
       {
        strint_errors++;
        putstr("Error: character is not alphanumeric -> ");
        putchar(s.charAt(x));
        putstr("\n");
        break;
       }
       if(c>=radix)
       {
        strint_errors++;
        putstr("Error: character is not a valid for current radix -> ");
        putchar(s.charAt(x));
        putstr("\n");
        break;
       }
       i*=radix;
       i+=c;
       x++;
      }
      return i;
     }
    
    }
    
    
  • 32-bit Windows chastehex update

    I made an update to the 32-bit version of chastehex for windows. Variable names have been changed to match the Linux version and the getarg function is now used instead of my old badly maintained code. Having all arguments handled by a separate header file helps keep things very organized.

    Writing this program with the Windows API in Assembly has taking a lot more time than the Linux version did, but this experience has made me appreciate the Linux system call interface a lot more. I also have working Windows versions of my Assembly programs now because I have made the effort. The chastehex program is only a small taste of what will be included in the Windows edition of Assembly Arithmetic Algorithms for Windows. So far, I have 10 chapters out of 15 to 20 planned.

    https://leanpub.com/assemblyarithmeticalgorithms-windows

    main.asm

    format PE console
    entry main
    
    include 'win32a.inc'        ;includes standard Windows 32-bit definitions and macros
    include 'chastelib-w32.asm' ;include standard library functions by Chastity
    include 'getarg-w32.asm'    ;include Chastity's getarg function for command line arguments
    
    main:
    
    mov [radix],16 ; Choose radix for integer output.
    mov [int_width],1
    
    call getarg ;this first call will get the command string
    cmp eax,0   ;did the getarg function return 0?
    jz help     ;if eax was zero, there are no args so we end the program safely after help message
    
    ;optionally display the command string
    ;call putstring
    ;call putline
    
    call getarg ;get next arg as file name
    cmp eax,0   ;did the getarg function return 0?
    jz help     ;if eax was zero, there are no args so we end the program safely after help message
    
    ;print the filename
    call putstring
    call putline
    
    mov [filename], eax ;save the filename to a permanent address
    
    jmp open_sesame
    
    help:
    
    mov eax,help_message
    call putstring
    
    jmp main_end
    
    open_sesame:
    
    ;open a file with the CreateFileA function
    ;https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
    
    ;call CreateFileA with Windows 32-bit calling convention
    
    push 0                  ;hTemplateFile = NULL: We are not using a template file
    push 0x80               ;dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL
    push 3                  ;dwCreationDisposition = OPEN_EXISTING
    push 0                  ;lpSecurityAttributes = NULL: No security attributes
    push 1                  ;dwShareMode = FILE_SHARE_READ (other programs can read this file)
    push 0x10000000         ;dwDesiredAccess = GENERIC_ALL access mode (Read+Write+Execute)
    push [filename]         ;lpFileName
    call [CreateFileA]
    
    
    ;check eax for file handle or error code
    ;call putint
    cmp eax,-1
    jnz file_ok
    
    mov eax,file_error_message
    call putstring
    call [GetLastError]
    call putint
    jmp main_end ;end program if the file was not opened
    
    ;this label is jumped to when the file is opened correctly
    file_ok:
    
    mov [fd],eax
    
    ;before we proceed, we also check for more arguments.
    
    ;get next arg (first one after name of program)
    call getarg
    cmp eax,0  ;did the getarg function return 0?
    jz hexdump ;proceed to normal hex dump if no more args
    
    ;otherwise interpret the arg as a hex address to seek to
    
    call strint
    mov [offset],eax
    
    ;seek to 32-bit address of file with SetFilePointer function
    ;https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfilepointer
    
    
    push 0           ;seek from beginning of file (SEEK_SET)
    push 0           ;NULL: We are not using a 64 bit address
    push [offset]    ;where we are seeking to
    push [fd]        ;seek within this file
    call [SetFilePointer]
    
    
    ;check for more args after the address argument
    call getarg
    cmp eax,0
    jz read_one_byte ;proceed to read one byte mode
    
    ;otherwise, write the rest of the arguments as bytes to the file!
    write_bytes:
    call strint
    mov [buf],al
    
    ;Windows 32-bit WriteFile system call
    ;https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile
    
    
    push 0               ;lpOverlapped = NULL
    push 0               ;lpNumberOfBytesWritten = NULL
    push 1               ;nNumberOfBytesToWrite = 1
    push buf             ;lpBuffer = address of data to write
    push [fd]            ;hFile = [fd] (copied there earlier)
    call [WriteFile]
    
    
    mov eax,[offset]
    inc [offset]
    mov [int_width],8
    call putint_and_space
    
    mov eax,0
    mov al,[buf]
    mov [int_width],2
    call putint_and_line
    
    ;check for more args
    call getarg ;get next arg as potential bytes to write
    cmp eax,0   ;did the getarg function return 0?
    jnz write_bytes
    ;continue write if the args still exist
    ;otherwise end program
    jmp main_end
    
    read_one_byte:
    
    ;read only 1 byte using Win32 ReadFile system call.
    
    
    push 0              ;Optional Overlapped Structure 
    push count     ;Store Number of Bytes Read from this call
    push 1              ;Number of bytes to read
    push buf     ;address to store bytes
    push [fd]  ;handle of the open file
    call [ReadFile]
    
    cmp [count],1 
    jz print_byte ;if less than one bytes read, there is an error
    
    mov eax,[offset]
    mov [int_width],8
    call putint_and_space
    mov eax,end_of_file
    call putstr_and_line
    
    jmp main_end
    
    print_byte:
    mov eax,[offset]
    mov [int_width],8
    call putint_and_space
    
    mov eax,0
    mov al,[buf]
    mov [int_width],2
    call putint_and_line
    
    jmp main_end
    
    hexdump:
    
    ;read bytes using Win32 ReadFile system call.
    push 0              ;Optional Overlapped Structure 
    push count     ;Store Number of Bytes Read from this call
    push 16             ;Number of bytes to read
    push buf     ;address to store bytes
    push [fd]  ;handle of the open file
    call [ReadFile]     ;all the data is in place, do the write thing!
    
    mov eax,[count]
    ;call putint
    ;mov eax,buf
    ;call putstring
    
    cmp eax,0
    jnz read_ok ;if more than zero bytes read, proceed to display
    
    jmp eof_end
    
    read_ok:
    call print_bytes_row
    
    jmp hexdump
    
    print_EOF:
    
    mov eax,[offset]
    mov [int_width],8
    call putint_and_space
    
    mov eax,end_of_file
    call putstr_and_line
    
    jmp main_end
    
    
    eof_end:
    ;before we end the program, let the user know End Of File was reached
    mov eax,end_of_file
    call putstr_and_line
    
    main_end:
    
    ;close the file
    push [fd]
    call [CloseHandle]
    
    ;Exit the process with code 0
    push 0
    call [ExitProcess]
    
    
    
    ;variables for displaying messages
    file_error_message db 'error: ',0
    end_of_file db 'EOF',0
    read_error_message db 'Failure during reading of file. Error number: ',0
    
    help_message db 'chastehex by Chastity White Rose',0Ah,0Ah
    db 'hexdump a file:',0Ah,0Ah,9,'chastehex file',0Ah,0Ah
    db 'read a byte:',0Ah,0Ah,9,'chastehex file address',0Ah,0Ah
    db 'write a byte:',0Ah,0Ah,9,'chastehex file address value',0Ah,0Ah
    db 'The file must exist',0Ah,0
    
    ;this function prints a row of hex bytes
    ;each row is 16 bytes
    print_bytes_row:
    mov eax,[offset]
    mov [int_width],8
    call putint_and_space
    
    mov ebx,buf
    mov ecx,[count]
    add [offset],ecx
    next_byte:
    mov eax,0
    mov al,[ebx]
    mov [int_width],2
    call putint_and_space
    
    inc ebx
    dec ecx
    cmp ecx,0
    jnz next_byte
    
    mov ecx,[count]
    pad_spaces:
    cmp ecx,0x10
    jz pad_spaces_end
    mov eax,space_three
    call putstring
    inc ecx
    jmp pad_spaces
    pad_spaces_end:
    
    ;optionally, print chars after hex bytes
    call print_bytes_row_text
    call putline
    
    ret
    
    space_three db '   ',0
    
    print_bytes_row_text:
    mov ebx,buf
    mov ecx,[count]
    next_char:
    mov eax,0
    mov al,[ebx]
    
    ;if char is below '0' or above '9', it is outside the range of these and is not a digit
    cmp al,0x20
    jb not_printable
    cmp al,0x7E
    ja not_printable
    
    printable:
    ;if char is in printable range,copy as is and proceed to next index
    jmp next_index
    
    not_printable:
    mov al,'.' ;otherwise replace with placeholder value
    
    next_index:
    mov [ebx],al
    inc ebx
    dec ecx
    cmp ecx,0
    jnz next_char
    mov [ebx],byte 0 ;make sure string is zero terminated
    
    mov eax,buf
    call putstring
    
    ret
    
    ;variables for managing file IO.
    filename dd ?
    count dd ? ;how many bytes are read with ReadFile operation
    buf db 16 dup ?,0
    fd dd ?
    offset dd ?
    
    ;FASM builds the Import Address Table (IAT) directly in the source file
    section '.idata' import data readable writeable
    
    library kernel32, 'KERNEL32.DLL'
    
    import kernel32,\
     GetStdHandle, 'GetStdHandle',\
     WriteFile, 'WriteFile',\
     ExitProcess, 'ExitProcess',\
     GetCommandLineA, 'GetCommandLineA',\
     CreateFileA, 'CreateFileA',\
     GetLastError, 'GetLastError',\
     SetFilePointer, 'SetFilePointer',\
     ReadFile, 'ReadFile',\
     CloseHandle, 'CloseHandle'
    
    

    chastelib-w32.asm

    ; chastelib assembly header file for 32 bit Windows
    ; This file is where I keep the source of my most important Assembly functions
    ; These are my string and integer output and conversion routines.
    
    ; To simplify documentation. The Accumulator/Arithmetic register
    ; (ax,eax,rax) depending on bit size shall be referred to as register A
    ; for the description of these core functions because the A register
    ; is treated special both by the Intel company and my code;
    
    ; putstring; Prints a zero terminated string from the address pointer to by A register.
    ; intstr;    Converts the number in A into a zero terminated string and points A to that address
    ; putint;    Prints the integer in A by calling intstr and then putstring.
    ; strint;    Converts the zero terminated string into an integer and sets A to that value
       
    ; Now, the source of the functions begins, with comments included for parts that I felt needed explanation.
    
    putstring:         ;print string pointed to by eax register
    
    push eax
    push ebx
    push ecx
    push edx
    
    mov ebx,eax             ;copy eax to ebx to be used as index to the string
    
    putstring_strlen_start: ;this loop finds the length of the string as part of the putstring function
    
    cmp [ebx],byte 0        ;compare byte at address ebx with 0
    jz putstring_strlen_end ;if comparison was zero, jump to loop end because we have found the length
    inc ebx
    jmp putstring_strlen_start
    
    putstring_strlen_end:
    sub ebx,eax ;subtract start pointer from current pointer to get length of string
    
    ;Windows 32-bit WriteFile system call
    
    push 0               ;lpOverlapped = NULL
    push 0               ;lpNumberOfBytesWritten = NULL
    push ebx             ;nNumberOfBytesToWrite = ebx
    push eax             ;lpBuffer = address of string to write
    push -11             ;STD_OUTPUT_HANDLE = Negative Eleven
    call [GetStdHandle]  ;Get Standard Handle for -11
    push eax             ;hFile = eax (returned from GetStdHandle)
    call [WriteFile]
    
    
    pop edx
    pop ecx
    pop ebx
    pop eax
    
    ret
    
    ; This is the location in memory where digits are written to by the intstr function
    ; The string of bytes and settings such as the radix and width are global variables defined below.
    
    int_string db 32 dup '?' ;reserve bytes for characters string for 32-bit binary integer
    
    int_string_end db 0 ;zero byte terminator for the integer string
    
    radix dd 2     ;radix or base for integer output. 2=binary, 8=octal, 10=decimal, 16=hexadecimal
    int_width dd 8 ;default width of integers. Extra zeros prefixed if more than 1
    
    ;this function creates a string of the integer in eax
    ;it uses the above radix variable to determine base from 2 to 36
    ;it then loads eax with the address of the string
    ;this means that it can be used with the putstring function
    
    intstr:
    
    mov ebx,int_string_end-1 ;find address of lowest digit
    mov ecx,1
    
    digits_start:
    
    mov edx,0;
    div dword [radix]
    cmp edx,10
    jb decimal_digit
    jnb hexadecimal_digit
    
    decimal_digit: ;we go here if it is only a digit 0 to 9
    add edx,'0'
    jmp save_digit
    
    hexadecimal_digit:
    sub edx,10
    add edx,'A'
    
    save_digit:
    
    mov [ebx],dl
    cmp eax,0
    jz intstr_end
    dec ebx
    inc ecx
    jmp digits_start
    
    intstr_end:
    
    prefix_zeros:
    cmp ecx,[int_width]
    jnb end_zeros
    dec ebx
    mov [ebx],byte '0'
    inc ecx
    jmp prefix_zeros
    end_zeros:
    
    mov eax,ebx ;point eax register to this string for putstring
    
    ret
    
    ;function to print string form of whatever integer is in eax
    ;The radix determines which number base the string form takes.
    ;Anything from 2 to 36 is a valid radix
    ;in practice though, only bases 2,8,10,and 16 will make sense to other programmers
    ;this function does not process anything by itself but calls the combination of my other
    ;functions in the order I intended them to be used.
    
    putint: 
    
    push eax
    push ebx
    push ecx
    push edx
    
    call intstr
    call putstring
    
    pop edx
    pop ecx
    pop ebx
    pop eax
    
    ret
    
    ;this function converts a string pointed to by eax into an integer returned in eax instead
    ;it is a little complicated because it has to account for whether the character in
    ;a string is a decimal digit 0 to 9, or an alphabet character for bases higher than ten
    ;it also checks for both uppercase and lowercase letters for bases 11 to 36
    ;finally, it checks if that letter makes sense for the base.
    ;For example, G to Z cannot be used in hexadecimal, only A to F can
    ;The purpose of writing this function was to be able to accept user input as integers
    ;This function is improved with error checking and uses the new strint_error variable
    ;The program can check this value after the call and see how many errors happened.
    
    strint_error db 0 ;declare a byte variable that keeps track of errors
    
    strint:
    
    mov ebx,eax ;copy string address from eax to ebx because eax will be replaced soon!
    mov eax,0
    mov byte[strint_error],0 ;set errors to 0 at the start of this function
    
    read_strint:
    mov ecx,0   ;zero ecx so only lower 8 bits are used
    mov cl,[ebx]
    inc ebx
    cmp cl,0    ;compare this byte with 0
    jz strint_end ; if comparison was zero, this is the end of string
    
    ;if char is below '0' or above '9', it is outside the range of these and is not a digit
    cmp cl,'0'
    jb not_digit
    cmp cl,'9'
    ja not_digit
    
    ;but if it is a digit, then correct and process the character
    is_digit:
    sub cl,'0'
    jmp process_char
    
    not_digit:
    ;it isn't a decimal digit, but it could be perhaps an alphabet character
    ;which could be a digit in a higher base like hexadecimal
    ;we will check for that possibility next
    
    ;if char is below 'A' or above 'Z', it is outside the range of these and is not capital letter
    cmp cl,'A'
    jb not_upper
    cmp cl,'Z'
    ja not_upper
    
    is_upper:
    sub cl,'A'
    add cl,10
    jmp process_char
    
    not_upper:
    
    ;if char is below 'a' or above 'z', it is outside the range of these and is not lowercase letter
    cmp cl,'a'
    jb not_lower
    cmp cl,'z'
    ja not_lower
    
    is_lower:
    sub cl,'a'
    add cl,10
    jmp process_char
    
    not_lower:
    
    ;if we have reached this point, result invalid and end function with error
    jmp strint_end_error
    
    process_char:
    
    cmp ecx,[radix] ;compare char with radix
    jnb strint_end_error ;if this value is above or equal to radix, it is too high despite being a valid digit/alpha
    
    mov edx,0 ;zero edx because it is used in mul sometimes
    mul dword [radix] ;mul eax with radix
    add eax,ecx
    
    jmp read_strint ;jump back and continue the loop if nothing has exited it
    
    strint_end_error:  ;we jump here if there was an error with one of the chars
    inc byte[strint_error] ;increment error counter because char invalid
    
    strint_end: ;we jump here when no errors happened
    
    ret
    
    ;The utility functions below simply print a space or a newline.
    ;these help me save code when printing lots of strings and integers.
    
    space db ' ',0 ;a string containing only a space
    
    putspace:
    push eax
    mov eax,space
    call putstring
    pop eax
    ret
    
    line db 0x0D,0x0A,0 ;a string containing only a newline
    
    ;the next function which pushes eax to the stack
    ;moves the address of the line string and prints it with putstring
    ;then it pops the original value of eax back from the stack before the function returns
    ;this allows me to print a newline anywhere in the code without a single register changing
    
    putline:
    push eax
    mov eax,line
    call putstring
    pop eax
    ret
    
    ;a function for printing a single character that is the value of al
    
    char: db 0,0
    
    putchar:
    push eax
    mov [char],al
    mov eax,char
    call putstring
    pop eax
    ret
    
    ;a small function just for the common operation of
    ;printing an integer followed by a space
    ;this saves a few bytes in the assembled code
    ;by reducing the number of function calls in the main program
    
    putint_and_space:
    call putint
    call putspace
    ret
    
    ;a small function just for the common operation of
    ;printing an integer followed by a line feed
    ;this saves a few bytes in the assembled code
    ;by reducing the number of function calls in the main program
    
    putint_and_line:
    call putint
    call putline
    ret
    
    ;a small function just for the common operation of
    ;printing a string followed by a line feed
    ;this saves a few bytes in the assembled code
    ;by reducing the number of function calls in the main program
    ;it also means we don't need to include a newline in every string!
    
    putstr_and_line:
    call putstring
    call putline
    ret
    
    

    getarg-w32.asm

    ;This is the Windows 32-bit source of the getarg function 
    
    ;The getarg function makes my assembly code for DOS and Windows easier to read
    ;by writing one function to handle all possible cases I will need for my tools.
    ;
    ;The first time it is run, it returns the whole command string or zero if no args are given
    ;Each time after that, it will give you the next argument, which is a substring of the original.
    ;When no more arguments are available, it will always return zero
    ;The program calling this is expected to check for this error and then terminate
    ;or print a message depending on the goals of that program
    
    ;A word of warning, though, this function has multiple return statements and is long
    ;However, it is fully featured in that it can recognize quoted strings as being the same argument
    ;This brings full compatibility for my DOS and Windows programs that use command line arguments.
    
    ;Because all of my programs are ported to DOS and Windows from Linux
    ;I found there to be conflicts in the way these operating systems did not
    ;handle the quoted strings.
    ;
    ;This same function is available in a separate file for DOS Assembly.
    
    getarg:
    
    mov ebx,[arguments_start] ;get the address of start of arguments
    cmp ebx,0 ;is this address zero? (meaning this function was not called before)
    jz get_arg_data ;if it was zero, then get the argument data for the first execution of this function
    
    ;if the start was not zero, then clearly arguments exist and addresses have been saved
    cmp ebx,[arguments_end]  ;is the address of the start and end the same?
    jnz find_next_string  ;if they are not the same, find the next sub string
    mov eax,0 ;otherwise, return eax as zero and check this in the main program
    
    ret
    
    find_next_string:
    
    mov ebx,[arguments_start] ;get address of current arg
    
    skip_spaces:
    
    cmp byte[ebx],' '   ;is this byte a space?
    jnz skip_spaces_end ;if it is not a space, we can end this loop
    inc ebx ;otherwise, go to next byte
    jmp skip_spaces ;and keep looping till we find non-space
    skip_spaces_end:
    mov eax,ebx ;copy this non-space address to eax register
    
    ;we have found a non-space which is the start of a printable string
    ;but we still have to find the next space and terminate it with a zero!
    
    ;however, there is a special case where we want a string to contain spaces. In this case, I have another routine!
    
    ;check for quoted strings
    cmp byte[ebx],0x22 ;is this a double quote -> "
    jz scan_quoted_string
    cmp byte[ebx],0x27 ;is this a single quote -> '
    jz scan_quoted_string
    
    find_space:
    cmp byte [ebx],' ' ;is this a space?
    jz found_space ;if this was a space, end the loop and terminate with zero
    
    ;we must also check to see if we have reached the terminating zero of the arguments string
    cmp byte[ebx],0 ;is this byte a zero?
    jz no_more_args ;if yes this string is already terminated
    
    inc ebx
    jmp find_space ; this char was not space, go to the next char
    found_space:
    mov byte[ebx],0 ;terminate this string
    
    inc ebx ;but go to the next byte
    mov [arguments_start],ebx ;and set the new start address for the next call
    
    ret ;We can return eax safely knowing the string ends in a zero
    
    scan_quoted_string:
    
    mov cl,byte[ebx] ;mov this quote type to cl
    inc ebx ;go to next byte
    mov eax,ebx ;set eax to this address which is assumed to be the start of a quoted string
    
    find_end_quote:
    cmp byte[ebx],cl ;is this the same quote we started with?
    jz found_end_quote ;if it is, end this loop
    
    ;we must also check to see if we have reached the terminating zero of the arguments string
    ;this avoids a crash if I forgot to add the second quotation mark in the arguments
    cmp byte[ebx],0 ;is this byte a zero?
    jz no_more_args ;if yes this string is already terminated
    
    inc ebx
    jmp find_end_quote
    found_end_quote:
    mov byte[ebx],0 ;terminate this string
    
    inc ebx ;but go to the next byte
    mov [arguments_start],ebx ;and set the new start address for the next call
    
    ret
    
    no_more_args:
    
    mov [arguments_start],ebx ;mov the start to where the string ended
    
    ;now that the start and end addresses are the same
    ;this function will always return zero
    ret
    
    ;this will happen first time this function is called to get the argument data
    get_arg_data:
    
    ;get command line argument string with this Windows API call
    ;it returns a pointer in the eax register
    
    call [GetCommandLineA]
    mov [arguments_start],eax ;but copy it to memory too
    
    
    ;the following loop is a modified strlen loop except that we don't
    ;care about how long the string is. We only need the pointer for where it ends
    
    mov ebx,eax  ;copy eax to ebx to be used in loop to find ending zero
    argend_find: ; this loop finds the zero at the end of the argument string
    cmp [ebx],byte 0 ; compare byte at address ebx with 0
    jz argend_found ; if comparison was zero, jump to loop end because we have found the length
    inc ebx
    jmp argend_find
    argend_found:
    mov [arguments_end],ebx ;save ebx address containing the zero byte
    
    mov ebx,eax ;mov the start of the arg string again before the next loop
    
    skip_prog_name:
    cmp byte[ebx],0   ;check for zero first (very important)
    jz no_args        ;if we found a zero before a space, there are no arguments after program name!
    cmp byte[ebx],' ' ;is this byte a space?
    jz skip_prog_name_end ;if it is a space, we can end this loop
    mov byte[ebx],' ' ;turn this byte into a space and therefore delete it
    inc ebx ; go to next byte
    jmp skip_prog_name ;and keep looping till we find space
    skip_prog_name_end:
    mov eax,ebx ;copy this non-space address to eax register
    ;return eax pointing to an address of string with arguments after program name
    ret
    
    no_args:
    mov eax,0
    ;in this case, we return zero because there are no args
    
    ret
    
    ;start and end default to address of zero, which means we have not tested the arguments yet
    arguments_start dd 0
    arguments_end dd 0